I am trying to setup a Derby database and insert some sample info into it for testing.
The code to get the tables I'd like is...
CREATE TABLE users(
userid varchar(128) primary key,
passwd_digest varchar(128)
);
CREATE TABLE customers(
cust_id int not null primary key(START WITH 1, INCREMENT BY 1),
cust_name varchar(128)
);
CREATE TABLE orders(
order_id int not null primary key,
cust_id int not null(START WITH 1, INCREMENT BY 1),
foreign key(cust_id) references customers(cust_id),
order_date date,
order_desc varchar(128)
);
Now when I try to insert the sample data into it using the following code:
insert into customers(cust_id, cust_name) values (3, 'Ringo');
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, 12.12.1957, 'A drumset');
I get the following error from IJ:
ERROR 42X01: Syntax error: Encountered ".1957" at line 1, column 82.
Issue the 'help' command for general information on IJ command syntax.
Any unrecognized commands are treated as potential SQL commands and executed directly.
Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
I've tried putting the date values in the following ways (disregard the other data, it's only the dates that appear to not work) :
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, 1957-12-12 00:00:00:000, 'A drumset');
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, 1957-12-12, 'A drumset');
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, "12-12-1957", 'A drumset');
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, DATE("12-12-1957"), 'A drumset');
insert into orders(order_id, cust_id, order_date, order_desc) values (4, 3, 12-12-1957, 'A drumset');
but they all produce similar errors including:
ERROR 42821: Columns of type 'DATE' cannot hold values of type 'INTEGER'.
I'm not sure why I'm getting these errors since I'm putting in values matching the format of Derby's docs (at least it looks that way to me, since it's not working I'm sure I've got it wrong somewhere).
Use the DATE or TIMESTAMP functions, or the JDBC escape syntax, whichever you prefer, to convert your literal values into date or timestamp data types.
Or write your insert logic in Java using PreparedStatement, and use the setDate() and setTimestamp() functions.
Various docs for the above:
DATE function: https://db.apache.org/derby/docs/10.15/ref/rrefdatefunc.html
TIMESTAMP function: https://db.apache.org/derby/docs/10.15/ref/rreftimestampfunc.html
JDBC Escape syntax for dates and times: https://db.apache.org/derby/docs/10.15/ref/rrefjdbc1020262.html
PreparedStatement: https://stackoverflow.com/a/18615191/193453
Related
I'm having some issues with my ResultSet using JDBC.
Here's my relation:
create table person (
person_id number(5) generated always as identity
minvalue 1
maxvalue 99999
increment by 1 start with 1
cycle
cache 10,
firstname varchar(10) not null,
lastname varchar(10) not null,
);
I'm trying to insert a (firstname, lastname) into the tuple and then get the person_id that comes out of it. Here's my JDBC code:
//connection is taken care of beforehand and is named con
prep = con.prepareStatement("insert into person (firstname, lastname) values (?, ?)", Statement.RETURN_GENERATED_KEYS);
prep.setString(1, firstname);
prep.setString(2, lastname);
prep.execute();
ResultSet generated = prep.getGeneratedKeys();
if (generated.next()) {
String key = generated.getString("0");
System.out.println(key);
}
This works all fine. But my problem is that the key should be an integer, not a String. Every time I run this, I get a ResultSet that contains a string of "AAA3vaAAGAAAFwbAAG", or something along those lines. I want to get the person_id so I can use it later in my Java program.
Is there something I'm doing wrong in regards to searching through the ResultSet or the execution of the statement itself?
tl;dr
int id = generated.getInt( 1 ) ;
Details
Your Question seems confused.
There are two forms of each get… method on ResultSet.
Pass a column number (an int)
Pass a column name (a String)
You seem to have combined the two into this:
String key = generated.getString( "0" ) ;
I doubt that you have a column named with a single digit zero. Besides being a poor choice of name, standard SQL forbids starting an identifier with a digit.
So that line makes no sense. Perhaps you meant the first column by using a zero 0 and mistakenly wrapped it in quotes, thereby transforming your intended int into an actual String.
Even that intention would be wrong. The ResultSet::getString documentation incorrectly describes the int as an “columnIndex”. Usually “index” means a zero-based counting offset. But actually ResultSet::getString( int ) requires you pass an ordinal number with counting starting at one. So getString( 0 ) is never valid.
So if you want to retrieve the value of your result set’s first column as text, do this:
String key = generated.getString( 1 ) ; // Retrieve first column of result set as text.
Yet again, this would be wrong in the context of your code. You are apparently attempting to retrieve the primary key values being generated during the INSERT. Your primary key column person_id is defined as number(5) which is not a textual type. So retrieving as a String is not appropriate.
NUMBER(5) is not standard SQL. If you happen to be using Oracle database, the doc says that would be an integer type with a precision of five, meaning numbers with up to five digits. So retrieve that as a integer type in Java by calling ResultSet::getInt.
int id = generated.getInt( 1 ) ; // Retrieve the new row’s ID from the first column of the result set of generated key values returned by the `INSERT` prepared statement.
My comments above are for databases in general. But for Oracle specifically, see the Answer by Mark Rotteveel explaining that Oracle database does not return the generated sequence number when calling getGeneratedKeys. Instead it returns ROWID pseudo-column.
Your problem is that Oracle by default returns the ROWID of the inserted record, and not the generated identifier. From Oracle JDBC Developer's Guide: Retrieval of Auto-Generated Keys:
If key columns are not explicitly indicated, then Oracle JDBC drivers
cannot identify which columns need to be retrieved. When a column name
or column index array is used, Oracle JDBC drivers can identify which
columns contain auto-generated keys that you want to retrieve.
However, when the Statement.RETURN_GENERATED_KEYS integer flag is
used, Oracle JDBC drivers cannot identify these columns. When the
integer flag is used to indicate that auto-generated keys are to be
returned, the ROWID pseudo column is returned as key. The ROWID
can be then fetched from the ResultSet object and can be used to
retrieve other columns.
So, if you use Statement.RETURN_GENERATED_KEYS, you'll get the ROWID, and you can then use that ROWID to select the inserted row to obtain the other values (including the generated identifier).
If you want to specifically retrieve the generated id, for Oracle you'll need to explicitly ask for that column as follows:
String[] columns = { "PERSON_ID" }
prep = con.prepareStatement(
"insert into person (firstname, lastname) values (?, ?)", columns);
prep.setString(1, firstname);
prep.setString(2, lastname);
prep.executeUpdate();
ResultSet generated = prep.getGeneratedKeys();
if (generated.next()) {
int key = generated.getInt("PERSON_ID");
System.out.println(key);
}
I have an SQLite database. I am trying to insert values (users_id, lessoninfo_id) in table bookmarks, only if both do not exist before in a row.
INSERT INTO bookmarks(users_id,lessoninfo_id)
VALUES(
(SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
(SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+")
WHERE NOT EXISTS (
SELECT users_id,lessoninfo_id from bookmarks
WHERE users_id=(SELECT _id FROM Users
WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+")))
This gives an error saying:
db error near where syntax.
If you never want to have duplicates, you should declare this as a table constraint:
CREATE TABLE bookmarks(
users_id INTEGER,
lessoninfo_id INTEGER,
UNIQUE(users_id, lessoninfo_id)
);
(A primary key over both columns would have the same effect.)
It is then possible to tell the database that you want to silently ignore records that would violate such a constraint:
INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
If you have a table called memos that has two columns id and text you should be able to do like this:
INSERT INTO memos(id,text)
SELECT 5, 'text to insert'
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');
If a record already contains a row where text is equal to 'text to insert' and id is equal to 5, then the insert operation will be ignored.
I don't know if this will work for your particular query, but perhaps it give you a hint on how to proceed.
I would advice that you instead design your table so that no duplicates are allowed as explained in #CLs answer below.
For a unique column, use this:
INSERT OR REPLACE INTO tableName (...) values(...);
For more information, see: sqlite.org/lang_insert
insert into bookmarks (users_id, lessoninfo_id)
select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;
This is the fastest way.
For some other SQL engines, you can use a Dummy table containing 1 record.
e.g:
select 1, 167 from ONE_RECORD_DUMMY_TABLE
I am using java DB database and NetBeans 8.0 for a desktop application
I am also using a PreparedStatement to query the database.
below is the code for creating the tables.
CREATE TABLE ALUMNUS (
ALUMNUA_ID INT NOT NULL PRIMARY KEY
GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
FIRST_NAME VARCHAR (45),
LAST_NAME VARCHAR (45),
OTHER_NAME VARCHAR (100)
);
CREATE TABLE DUES (
ID INT NOT NULL PRIMARY KEY
GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
PAYMENT_YEAR DATE,
AMOUNT DOUBLE,
ALUMNUS_ID INT
);
--FOREIGN KEY
ALTER TABLE APP.DUES
ADD FOREIGN KEY (ALUMNUS_ID) REFERENCES APP.ALUMNUS(ID);
Now I want to insert, delete and update the foreign key values in APP.DUES table. what is the best option; trigger , stored procedure or the preparedstatement?
An example will be good.
If you want to primarily insert into the DUES table, you would use a sub select in SQL. I havent tested it with Java DB, but it basically looks like:
INSERT INTO DUES(PAYMENT_YEAR, AMOUNT,ALUMNUS_ID)
VALUES(2014, 100.0,
(SELECT ALUMNUA_ID from ALUMNUS where ...));
You need to catch the "not found" error case and prepend a INSERT (and need to catch the duplicate case for that as well).
See also: Insert Data Into Tables Linked by Foreign Key
I am using java with jdbc to connecto to a MySQL database. I need to set one of date fields as empty. This field defaults to NULL and if i insert an empty string, the database creates a 0000-00-00 value in cell.
I then need to use that value in a report(jasperreport) and of course it can't be like 0000-00-00.
What I've tried to do:
Use if..then clause in query but i can't set it properly.
Has anyone an idea on how to get these date as empty string from the database (when I am calling jasperreport I am giving him just a sql query).
Set it to NULL in the DB, don't set it to an empty string.
Then write a select query which uses:
COALESCE(dt,'')
where dt is your date field.
Try this script as a test.
create table test(id int, dt datetime);
insert into test(id, dt) values (1, CURDATE());
insert into test(id, dt) values (2, NULL);
insert into test(id, dt) values (3, NOW());
insert into test(id, dt) values (4, NULL);
select
id, coalesce(dt, '') as dt
from
test;
I'm using UNION ALL to combine the results of several SELECT queries into one ResultSet. I use constant field values to identify which statement produced each row. This works well with MySQL, but Java DB is throwing SQLSyntaxErrorException, pointing at the comma after the first constant field value.
What syntax is used to select constant field values in SELECT queries against JavaDB databases?
The first SELECT has ~100 columns with varying data types, and the following SELECTs are padded to match the correct number of columns. I've it here. The statements currently look like this:
select
(0, ID, NAME_FIRST, NAME_LAST)
from person
where ID=500
union all
select
(1, COMMTYPE_ID, NULL, NULL)
from person_commtype
where PERSON_ID=500
Which throws the following exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "," at line 2, column 7.
I have also tried casting the value, and removing the parentheses, like so:
select
(cast(0 as integer), ID, NAME_FIRST, NAME_LAST)
from person
where ID=500
select
0, ID, NAME_FIRST, NAME_LAST
from person
where ID=500
Remove the brackets from around your list of fields in the SELECT clause.
select
0, ID, NAME_FIRST, NAME_LAST
from person
where ID=500
union all
select
1, COMMTYPE_ID, NULL, NULL
from person_commtype
where PERSON_ID=500
The problem is that Apache Derby doesn't support
select null from test
Instead you have to cast the null to the right type:
select cast(null as varchar(255)) from test
So the query would look like:
select
0, ID, NAME_FIRST, NAME_LAST
from person where ID=500
union all
select
1, COMMTYPE_ID,
cast(NULL as varchar(255)),
cast(NULL as varchar(255))
from person_commtype where PERSON_ID=500
You also have to remove the brackets around your column list, because that's not standard SQL syntax.
Try putting your numbers in single quotes.
select
('0', ID, NAME_FIRST, NAME_LAST)
from person
where ID=500
union all
select
('1', COMMTYPE_ID, NULL, NULL)
from person_commtype
where PERSON_ID=500