I have a trouble inserting data into a sqlite3 database with an id autoincrement. Here is what I have tried so far:
begin
db = SQLite3::Database.open db_name
db.execute "CREATE TABLE IF NOT EXISTS Audit(
id INTEGER PRIMARY KEY AUTOINCREMENT,
module TEXT,
hostname TEXT,
criticity TEXT,
raw_data TEXT
);"
rescue SQLite3::Exception => e
puts e.backtrace
ensure
db.close if db
end
And I insert data like this:
db.execute("INSERT INTO Audit VALUES (module,hostname,criticity,raw_data)",
check,
hostname,
raw_data,
criticity
)
Here is the error:
#<SQLite3::SQLException: table Audit has 5 columns but 4 values were supplied>
I don't know how to supply the id values as it should be auto-incremented
That's an odd error I get SQLite3::SQLException: no such column: module
I think you have the wrong format you could do this format try,
db.execute("INSERT INTO Audit (module,hostname,criticity,raw_data) VALUES (?,?,?,?) ", 'module', 'host', 'criticity', "\x01\x00\x00\x00\x01")
Results:
sqlite> SELECT * FROM Audit;
1|module|host|criticity|☺
Just as guess try insert null value.
db.execute("INSERT INTO Audit VALUES (id, module,hostname,criticity,raw_data)",
null,
check,
hostname,
raw_data,
criticity
)
Also look at https://www.sqlite.org/faq.html#q1 it states a A column declared INTEGER PRIMARY KEY will autoincrement
Related
My Problem:
I have an app and users who login have a department authorization list:
DEPT1, DEPT2, DEPT3, ..., DEPT5000, DEPT5001, ...
Most users have 5,000+ departments assigned to their profile.
I am tasked with writing a data model + application code that will 'snapshot' their list of authorized departments every time a user logs in so that we may refer to what that user was authorized to do (note: the DEPT IDs are not neatly numbered like in this example).
What I've tried:
My first thought was to turn the list of departments into a long CSV string and store it as a CLOB:
CREATE TABLE UI_SECURITY_CONFIG (
SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
DEPTSCSV CLOB NOT NULL
);
And each DEPTSCSV CLOB would be unique. If the user has the same security profile as someone else who's logged in previously, it would just select that security config. Otherwise, it would create a new row. Basically, do a select where DEPTSCSV = 'DEPT1, DEPT2, DEPT3 ...' and if it doesn't exist, insert it. But this approach failed because a huge string that big (25,000+ chars) isn't comparable:
SELECT * FROM UI_SECURITY_CONFIG WHERE DEPTSCSV = 'DEPT0001, DEPT0002, DEPT0003, ..., DEPT5001, DEPT5002'
SQL Error [1704] [42000]: ORA-01704: string literal too long
Solution attempt #2:
So then I thought about making each item in the CSV its own row in the table:
CREATE TABLE UI_SECURITY_CONFIG (
SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
DEPTID VARCHAR2(20) NOT NULL
);
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0002');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0003');
...
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5002');
But I'm struggling to write the SQL select that would be an efficient matching algorithm to find if a SECURITY_CONFIG_ID exists that matches exactly the list of Departments.
I'm not even sure there is an efficient way to solve this problem.
Solution Attempt #3:
Ask Stack Overflow. What would you do?
I was able to achieve strategy #1. The Application code (Java) handled the CLOB comparison better than my SQL client (DBeaver) with PreparedStatement:
String sql = "SELECT SECURITY_CONFIG_ID FROM UI_SECURITY_CONFIG WHERE dbms_lob.compare(DEPTSCSV, ?) = 0";
String DEPTSCSV = "DEPT0001, DEPT0002, ...";
try(PreparedStatement objStmt = objConn.prepareStatement(sql)) {
Clob clob1 = objConn.createClob();
clob1.setString(1, DEPTSCSV);
objStmt.setClob(1, clob1);
ResultSet result = objStmt.executeQuery();
...
}
I have a spring boot application and I trying to initialize some data on application startup.
This is my application properties:
#Database connection
spring.datasource.url=jdbc:h2:mem:test_db
spring.datasource.username=...
spring.datasource.password=...
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.initialize=true
spring.datasource.schema=schema.sql
spring.datasource.data=schema.sql
#Hibernate configuration
#spring.jpa.hibernate.ddl-auto = none
This is schema.sql:
CREATE TABLE IF NOT EXISTS `Person` (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`first_name` VARCHAR(50) NOT NULL,
`age` INTEGER NOT NULL,
PRIMARY KEY(`id`)
);
and data.sql
INSERT INTO `Person` (
`id`,
`first_name`,
`age`
) VALUES (
1,
'John',
20
);
But I got 'Syntax error in SQL statement' on application startup:
19:08:45.642 6474 [main] INFO o.h.tool.hbm2ddl.SchemaExport - HHH000476: Executing import script '/import.sql'
19:08:45.643 6475 [main] ERROR o.h.tool.hbm2ddl.SchemaExport - HHH000388: Unsuccessful: CREATE TABLE Person (
19:08:45.643 6475 [main] ERROR o.h.tool.hbm2ddl.SchemaExport - Syntax error in SQL statement "CREATE TABLE PERSON ( [*]"; expected "identifier"
Syntax error in SQL statement "CREATE TABLE PERSON ( [*]"; expected "identifier"; SQL statement:
I can't understand, what's wrong with this SQL.
Try this code. Remove PRIMARY KEY(id) and execute it.
CREATE TABLE IF NOT EXISTS `Person` (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`first_name` VARCHAR(50) NOT NULL,
`age` INTEGER NOT NULL
);
This error results from the structure of the CREATE TABLE declaration.
It will be the result when you have an extra comma in the end of your SQL declaration--no column declaration following the comma. For example:
CREATE TABLE IF NOT EXISTS `Person` (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`first_name` VARCHAR(50) NOT NULL,
`age` INTEGER NOT NULL, --note this line has a comma in the end
);
That's because CREATE TABLE expects a list of the columns that will be created along with the table, and the first parameter of the column is the identifier. As you check here, the column declaration follows the structure:
identifier datatype <constraints> <autoincrement> <functions>
Thus, in your case, as #budthapa and #Vishwanath Mataphati have mentioned, you could simply remove the PRIMARY KEY(id) line from the CREATE TABLE declaration. Moreover, you have already stated that id is a primary key on the first line of the column definitions.
In case you do not have a statement as the PRIMARY KEY declaration, be sure to check for the extra comma following your last column declaration.
Try this, as you have used Table_name
CREATE TABLE IF NOT EXISTS Person (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
age INTEGER NOT NULL
);
I was add below in to application.properties and it work for me
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.globally_quoted_identifiers_skip_column_definitions = true
What helped in my case was removing single quotes from the table name in my insert query
I had to change this:
INSERT INTO 'translator' (name, email) VALUES ('John Smith', 'john#mail.com');
to this:
INSERT INTO translator (name, email) VALUES ('John Smith', 'john#mail.com');
You set auto increment id, so you can't insert new record with id.
Try INSERT INTO `Person` (
`first_name`,
`age`
) VALUES (
'John',
20
);
I ran into same issue. I fixed that with these application.properties:
spring.jpa.properties.hibernate.connection.charSet=UTF-8
spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor=org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
Some issue with multi-line and default encoding.
have two tables A and B both same structure except B has one addition extra column inserting as "null". I need to Retain all data from A in B when I insert like below query it is inserting duplicate values because of that getting "primary Key violation error" when I try to create the "CONSTRAINT PK_Details_A PRIMARY KEY" Please help on this to avoid duplicate values while inserting the records.
Thanks in advance.
Insert into tableB(
id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary
,Notional
)
select id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary,null
from tableA;
EDIT
Primary key definition for B copied from comment below:
ALTER TABLE B
ADD CONSTRAINT PK_B
PRIMARY KEY ( oid)
USING INDEX ( CREATE UNIQUE INDEX PK_B ON B ( oid )
I have a table in a SQLite database created with the code below. Note the compound primary key:
db.create_table(:person_hash) do
Integer :person_id
Bignum :hash // MD5 hash in hex stored as numeric: hash.to_i(16)
primary_key [:person_id, :hash]
end
This table has some rows already:
puts db[:person_hash].where(:person_id => 285577).all
# {:person_id=>285577, :hash=>306607097659338192312932577746542919680}
Now, when I try to insert this:
db[:person_hash].insert({:person_id=>285577, :hash=>306607097659338206333361532286405644297})
I get this:
SQLite3::ConstraintException: columns person_id, hash are not unique (Sequel::DatabaseError)
If the row does not already exist in the table, how can it be a duplicate?
I tried inserting another hash for the same person ID instead, and it worked without problems.
This appears to be a bug in SQLite:
$ sqlite3
SQLite version 3.8.9 OpenBSD
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE person_hash (person_id integer, hash bigint, primary key (person_id, hash));
sqlite> INSERT INTO person_hash VALUES (285577, 306607097659338192312932577746542919680);
sqlite> INSERT INTO person_hash VALUES (285577, 306607097659338206333361532286405644297);
Error: UNIQUE constraint failed: person_hash.person_id, person_hash.hash
I'm using Ruby Sequel (ORM gem) to connect to a Postgres database. I'm not using any models. My insert statements seem to have a "returning null" appended to them automatically (and thusly won't return the newly inserted row id/pk). What's the use of this? And why is this the default? And more importantly, how do I disable it (connection wide)?
Also, I noticed there's a dataset.returning method but it doesn't seem to work!
require 'sequel'
db = Sequel.connect 'postgres://user:secret#localhost/foo'
tbl = "public__bar".to_sym #dynamically generated by the app
dat = {x: 1, y: 2}
id = db[tbl].insert(dat) #generated sql -- INSERT INTO "public"."bar" ("x", "y") VALUES (1, 2) RETURNING NULL
Don't know if it matters but the table in question is inherited (using postgres table inheritance)
ruby 1.9.3p392 (2013-02-22) [i386-mingw32]
sequel (3.44.0)
--Edit 1 -- After a bit of troubleshooting--
Looks like the table inheritance COULD BE the problem here. Sequel seems to run a query automatically to determine the pk of a table (in my case the pk's defined on a table up the chain), not finding which, perhaps the "returning null" is being appended?
SELECT pg_attribute.attname AS pk FROM pg_class, pg_attribute, pg_index, pg_namespace WHERE pg_class.oid = pg_attribute.attrelid AND pg_class.relnamespace = pg_namespace.oid AND
pg_class.oid = pg_index.indrelid AND pg_index.indkey[0] = pg_attribute.attnum AND pg_index.indisprimary = 't' AND pg_class.relname = 'bar'
AND pg_namespace.nspname = 'public'
--Edit 2--
Yup, looks like that's the problem!
If you are using PostgreSQL inheritance please note that the following are not inherited:
Primary Keys
Unique Constraints
Foreign Keys
In general you must declare these on each child table. Do for example:
CREATE TABLE my_parent (
id bigserial primary key,
my_value text not null unique
);
CREATE TABLE my_child() INHERITS (my_parent);
INSERT INTO my_child(id, my_value) values (1, 'test');
INSERT INTO my_child(id, my_value) values (1, 'test'); -- works, no error thrown
What you want instead is to do this:
CREATE TABLE my_parent (
id bigserial primary key,
my_value text not null unique
);
CREATE TABLE my_child(
primary key(id),
unique(my_value)
) INHERITS (my_parent);
INSERT INTO my_child(id, my_value) values (1, 'test');
INSERT INTO my_child(id, my_value) values (1, 'test'); -- unique constraint violation thrown
This sounds to me like you have some urgent DDL issues to fix.
You could retrofit the second's constraints onto the first with:
ALTER TABLE my_child ADD PRIMARY KEY(id);
ALTER TABLE my_child ADD UNIQUE (my_value);