How to crate a now row without knowing the any of the columns of the table and using default values therefore?
In sqlite3 I simply do:
sqlite> CREATE TABLE t ("id" INTEGER PRIMARY KEY, "text" TEXT DEFAULT "hello world");
sqlite> INSERT INTO t DEFAULT VALUES;
sqlite> SELECT * FROM t;
1|hello world
But in sqlite2.8.17 I get:
sqlite> INSERT INTO t DEFAULT VALUES;
SQL error near 'DEFAULT': Syntax error.
Is there a way to do this right in sqlite2 or do I need to give the values manually in the insert statement?
You have to specify at least one value; all the others will then get their default values.
The rowid automatically gets a value when you specify NULL, so you can use that one:
INSERT INTO t(id) VALUES(NULL);
Related
The question is simple:
In SQLite, if I choose to AutoIncrement a primary key of type NUMERIC which has a check constraint like CHECK(LENGTH(ID) == 10), will it work correctly inserting the first value as 0000000001 and so on?
No, that does not work. Adding a check does not magically also add a way of fullfilling the check to insert the data.
See this SQLFiddle.
If you want to restrict the value of an autoincrement column like that, you need to seed the internal sequence table. (There are other ways.)
create table foo (
foo_id integer primary key autoincrement,
other_columns char(1) default 'x',
check (length(foo_id) = 10 )
);
insert into sqlite_sequence values ('foo', 999999999);
Application code is allowed to modify the sqlite_sequence table, to
add new rows, to delete rows, or to modify existing rows.
Source
insert into foo (other_columns) values ('a');
select * from foo;
1000000000|a
Trying to insert 11 digits makes the CHECK constraint fail.
insert into foo values (12345678901, 'a');
Error: CHECK constraint failed: foo
One alternative is to insert a "fake" row with the first valid id number immediately after creating the table. Then delete it.
create table foo(...);
insert into foo values (1000000000, 'a');
delete from foo;
Now you can insert normally.
insert into foo (other_columns) values ('b');
select * from foo;
1000000001|b
In fact the ID's length is 1, so it doesn't work.
When I run sqlite3 foo.db from cmd (Windows) and enter these commands (assuming TABLE 'test' does not exist):
sqlite> CREATE TABLE test (id integer PRIMARY KEY, name char(1));
sqlite> INSERT INTO test (name) VALUES ('aaaaaa');
there are no errors. To verify,
//Input
sqlite> SELECT * FROM test;
//Output
1|aaaaaa
Again, to verify,
sqlite> .schema test
CREATE TABLE test (id integer PRIMARY KEY, name char(1)); //output
and the schema isn't changed.
Is there something wrong, especially with the name char(1) part? For the record, I compiled SQLite3 using MinGW64 with
--host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw // where /mingw is included in my PATH
Thanks in advance.
As there is no types in SQLite, the question is meaningless. All TEXT values are the same and are stored as "unlimited" (up to SQLITE_MAX_LENGTH) length strings.
What you see is a WAD: "working as designed".
SQLite doesn't enforce the length of a char(n) or varchar(n) column as it's declared in a CREATE TABLE statement. But you can enforce length restrictions using a CHECK constraint.
sqlite> create table test (
...> id integer primary key,
...> name char(1),
...> check (length(name)<=1)
...> );
sqlite> INSERT INTO test (name) VALUES ('aaaaaa');
Error: CHECK constraint failed: test
I'm trying to insert data into a table. I would like to insert the row if the column doesn't have the data already - regardless of the other columns.
CREATE TABLE t (
id INTEGER PRIMARY KEY,
name VARCHAR,
other INT
);
INSERT OR IGNORE INTO t (name) VALUES ('a');
INSERT OR IGNORE INTO t (name) VALUES ('a');
INSERT OR IGNORE INTO t (name) VALUES ('a');
With the above snippet I end up with 3 rows, not 1 as I would have thought. If it matters the actual sql is happening inside of a INSTEAD OF INSERT trigger, this is just a simple test case.
Replace
CREATE TABLE t (
id INTEGER PRIMARY KEY,
name VARCHAR,
other INT
);
with
CREATE TABLE t (
id INTEGER PRIMARY KEY,
name VARCHAR UNIQUE,
other INT
);
Then you will get
sqlite> CREATE TABLE t (
...> id INTEGER PRIMARY KEY,
...> name VARCHAR UNIQUE,
...> other INT
...> );
sqlite> INSERT OR IGNORE INTO t (name) VALUES ('a');
sqlite> INSERT OR IGNORE INTO t (name) VALUES ('a');
sqlite> INSERT OR IGNORE INTO t (name) VALUES ('a');
sqlite> select * from t ;
1|a|
That would only work for the primary key field or unique constraints:
The optional conflict-clause allows the specification of an
alternative constraint conflict resolution algorithm to use during
this one INSERT command.
Further:
The ON CONFLICT clause applies to UNIQUE and NOT NULL constraints
(and to PRIMARY KEY constraints which for the purposes of this section
are the same thing as UNIQUE constraints). The ON CONFLICT algorithm
does not apply to FOREIGN KEY constraints. There are five conflict
resolution algorithm choices: ROLLBACK, ABORT, FAIL, IGNORE, and
REPLACE. The default conflict resolution algorithm is ABORT.
Can I create a database constraint on a TEXT column in SQLite disallowing the value of the column to be empty string ""?
I want to allow the column to be null, but disallow empty string.
Yes you can:
sqlite> create table foo (bar TEXT, CHECK(bar <> ''));
sqlite> insert into foo values (NULL);
sqlite> insert into foo values ('bla');
sqlite> insert into foo values ('');
Error: constraint failed
You can use a CHECK constraint (http://www.sqlite.org/lang_createtable.html):
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> create table example(col, CHECK (col is null or length(col) > 0));
sqlite> insert into example values ('');
SQL error: constraint failed
sqlite> insert into example values (null);
sqlite> insert into example values ('sample');
sqlite> .nullvalue NULL
sqlite> select col from example;
NULL
sample
As far as i know doesn't exist a similar constraint in SQLite, but maybe you can workaround with a Trigger that on INSERT and/or UPDATE automatically change the string empty in NULL.
In MS SQL I would use
SET IDENTITY INSERT ON
How do I do something similar in SQLite. I am trying to upgrade a database and want to maintain the IDs from the original
Thanks
You don't need to set IDENTITY INSERT, because it is always possible to set the value explicitly. With SQLite, you can just insert into the ROWID column:
drop table test;
create table test(name varchar);
insert into test(name) values('Hello');
insert into test(rowid, name) values(10, 'World');
select rowid, name from test;
The same if you use an autoincrement primary key:
drop table test;
create table test(id integer primary key autoincrement, name varchar);
insert into test(name) values('Hello');
insert into test values(10, 'World');
select * from test;
See also http://www.sqlite.org/autoinc.html