I have the following SQLite query:
CREATE TABLE Logs ( Id integer IDENTITY (1, 1) not null CONSTRAINT PKLogId PRIMARY KEY, ...
IDENTITY (1, 1) -> What does this mean?
PKLogId what is this? This doesn't seem to be defined anywhere
I want Id to be integer primary key with autoincrement. I would like to be able to insert into this Logs table omitting Id column in my query. I want Id to be automatically added and incremented. Is this possible? How can I do this?
At the moment when I try to insert without Id I get:
Error while executing query: Logs.Id may not be NULL
I'm not sure whether you're actually using SQLite according to the syntax of your example.
If you are, you may be interested in SQLite FAQ #1: How do I create an AUTOINCREMENT field?:
Short answer: A column declared INTEGER PRIMARY KEY will
autoincrement.
Change it to:
CREATE TABLE Logs ( Id integer PRIMARY KEY,....
If you are, you may be interested in SQLite FAQ #1: How do I create an AUTOINCREMENT field?:
Short answer: A column declared INTEGER PRIMARY KEY will auto increment.
This in fact is not entirely accurate. An integer primary key will indeed increment, however if the table drops all rows, it starts from the beginning again, It is important if you want to have all associated records tied correctly to use the autoincrement description after the primary key declaration on the integer field.
Related
Warning: possible duplicate
Hi,
I have the following table
CREATE TABLE names (
id uuid DEFAULT uuid_generate_v4(),
name VARCHAR(10) NOT NULL UNIQUE,
PRIMARY KEY (id)
);
Now, uuid basically says, use a unique VARCHAR(10) as an index. The question that I have is: can't I just use name as an id, since it's unique anyway and takes up the same amount of space or would this have negative impact on foreign keys?
I'm not new to SQL, I've just never came across this conflict and now I'm wondering if I've been using some concepts wrong the whole time.
Is there any difference between INT PRIMARY KEY and INTEGER PRIMARY KEY when defining a schema for a table?
When int primary key is used, I got sqlite_autoindex thing generated;
when integer primary key , I got sqlite_sequence table generated.
what's the difference? what side effects can have the first and second variants?
UPDATE: SQLite's ROWID column is now a 64-bit integer:
In SQLite, a column with type INTEGER PRIMARY KEY is an alias for the ROWID (except in WITHOUT ROWID tables) which is always a 64-bit signed integer.
It is all explained in SQLite 3 documentation:
2.0 The INTEGER PRIMARY KEY
One exception to the typelessness of SQLite is a column whose type is INTEGER PRIMARY KEY. (And you must use "INTEGER" not "INT". A column of type INT PRIMARY KEY is typeless just like any other.) INTEGER PRIMARY KEY columns must contain a 32-bit signed integer. Any attempt to insert non-integer data will result in an error.
INTEGER PRIMARY KEY columns can be used to implement the equivalent of AUTOINCREMENT. If you try to insert a NULL into an INTEGER PRIMARY KEY column, the column will actually be filled with an integer that is one greater than the largest key already in the table. Or if the largest key is 2147483647, then the column will be filled with a random integer. Either way, the INTEGER PRIMARY KEY column will be assigned a unique integer. You can retrieve this integer using the sqlite_last_insert_rowid() API function or using the last_insert_rowid() SQL function in a subsequent SELECT statement.
Yes, there is a difference: INTEGER is a special case in SQLite, when the database does not create a separate primary key, but reuses the ROWID column instead. When you use INT (or any other type that "maps" to INTEGER internally) a separate primary key is created.
That is why you see sqlite_autoindex created for the INT primary key, and no index created for the one of type INTEGER: SQLite reuses a built-in indexing structure for the integer primary key, rendering the autoindex unnecessary.
That is why the INTEGER primary key is more economical, both in terms of storage and in terms of performance.
See this link for details.
Just to add albeit implied already on the answers here. The INTEGER PRIMARY KEY column that you created is simply an alias for ROWID or _ROWID_ or OID. And if the AUTOINCREMENT keyword is added then every new record inserted is an increment of 1 of the last ROWID and the last ROWID is kept by an sqlite internal table named sqlite_sequence.
See link here and here
On the other hand if you declare a column as INT PRIMARY KEY sqlite create an automatic index (hence the sqlite_autoindex) to keep track of the value inserted in the primary key to make sure it is unique.
I have a table with only 1 primary column (nvarchar), as in the designer, it's marked as primary key and not allow nulls. But by somehow, there is a row in that table with the key value being empty, it's of course not null and doesn't duplicate with any other rows in the primary key column and there isn't any conflict or violation occurring.
However as far as I know, that kind of value (empty) is not allowed for a primary column in SQL Server. I wonder if there is any option to turn on to make it work properly. Or I have to check the value myself through CHECK constraint or right in C# code (before updating).
Your help would be highly appreciated. Thanks!
"Empty-string" is a string with length of zero. It is NOT NULL, so it doesn't violate a null check. It most certainly IS an allowed value for a character-based primary key column in SQL Server. If the empty string value is not allowed by the business, a check constraint would be the best way to implement this as a business rule. That way, clients which might not know about the rule can't violate it.
This code runs without violations in SQL Server, I just tested it just to be sure.
create table TestTable (
myKey varchar(10) primary key,
myData int
)
GO
insert TestTable
select '', 1
I have these relationships:
User(uid:integer,uname:varchar), key is uid
Recipe(rid:integer,content:text), key is rid
Rating(rid:integer, uid:integer, rating:integer) , key is (uid,rid).
I built the table in the following way:
CREATE TABLE User(
uid INTEGER PRIMARY KEY ,
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY,
content VARCHAR NOT NULL
);
Now for the Rating table: I want it to be impossible to insert a uid\rid that does not exist in User\Recipe.
My question is: which of the following is the correct way to do it? Or please suggest the correct way if none of them are correct. Moreover, I would really appreciate if someone could explain to me what is the difference between the two.
First:
CREATE TABLE Rating(
rid INTEGER,
uid INTEGER,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid),
FOREIGN KEY (rid) REFERENCES Recipes,
FOREIGN KEY (uid) REFERENCES User
);
Second:
CREATE TABLE Rating(
rid INTEGER REFERENCES Recipes,
uid INTEGER REFERENCES User,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
EDIT:
I think User is problematic as a name for a table so ignore the name.
Technically both versions are the same in Postgres. The docs for CREATE TABLE say so quite clearly:
There are two ways to define constraints: table constraints and column constraints. A column constraint is defined as part of a column definition. A table constraint definition is not tied to a particular column, and it can encompass more than one column. Every column constraint can also be written as a table constraint; a column constraint is only a notational convenience for use when the constraint only affects one column.
So when you have to reference a compound key a table constraint is the only way to go.
But for every other case I prefer the shortest and most concise form where I don't need to give names to stuff I'm not really interested in. So my version would be like this:
CREATE TABLE usr(
uid SERIAL PRIMARY KEY ,
uname TEXT NOT NULL
);
CREATE TABLE recipes(
rid SERIAL PRIMARY KEY,
content TEXT NOT NULL
);
CREATE TABLE rating(
rid INTEGER REFERENCES recipes,
uid INTEGER REFERENCES usr,
rating INTEGER NOT NULL CHECK (rating between 0 and 5),
PRIMARY KEY(rid,uid)
);
This is a SQL Server based solution, but the concept applies to most any RDBMS.
Like so:
CREATE TABLE Rating (
rid int NOT NULL,
uid int NOT NULL,
CONSTRAINT PK_Rating PRIMARY KEY (rid, uid)
);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_Recipies FOREIGN KEY(rid)
REFERENCES Recipies (rid);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_User FOREIGN KEY(uid)
REFERENCES User (uid);
This ensures that the values inside of Rating are only valid values inside of both the Users table and the Recipes table. Please note, in the Rating table I didn't include the other fields you had, just add those.
Assume in the users table you have 3 users: Joe, Bob and Bill respective ID's 1,2,3. And in the recipes table you had cookies, chicken pot pie, and pumpkin pie respective ID's are 1,2,3. Then inserting into Rating table will only allow for these values, the minute you enter 4 for a RID or a UID SQL throws an error and does not commit the transaction.
Try it yourself, its a good learning experience.
In Postgresql a correct way to implement these tables are:
CREATE SEQUENCE uid_seq;
CREATE SEQUENCE rid_seq;
CREATE TABLE User(
uid INTEGER PRIMARY KEY DEFAULT nextval('uid_seq'),
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY DEFAULT nextval('rid_seq'),
content VARCHAR NOT NULL
);
CREATE TABLE Rating(
rid INTEGER NOT NULL REFERENCES Recipes(rid),
uid INTEGER NOT NULL REFERENCES User(uid),
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
There is no real difference between the two options that you have written.
A simple (i.e. single-column) foreign key may be declared in-line with the column declaration or not. It's merely a question of style. A third way should be to omit foreign key declarations from the CREATE TABLE entirely and later add them using ALTER TABLE statements; done in a transaction (presumable along with all the other tables, constraints, etc) the table would never exist without its required constraints. Choose whichever you think is easiest fora human coder to read and understand i.e. is easiest to maintain.
EDIT: I overlooked the REFERENCES clause in the second version when I wrote my original answer. The two versions are identical in terms of referential integrity, there are just two ways of syntax to do this.
I am trying to create a table with an auto-incrementing primary key in Sqlite3. I am not sure if this is really possible, but I am hoping to only have to designate the other fields.
For example:
CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));
Then, when I add a value, I was hoping to only have to do:
INSERT INTO people
VALUES ("John", "Smith");
Is this even possible?
I am running sqlite3 under cygwin in Windows 7.
You get one for free, called ROWID. This is in every SQLite table whether you ask for it or not.
If you include a column of type INTEGER PRIMARY KEY, that column points at (is an alias for) the automatic ROWID column.
ROWID (by whatever name you call it) is assigned a value whenever you INSERT a row, as you would expect. If you explicitly assign a non-NULL value on INSERT, it will get that specified value instead of the auto-increment. If you explicitly assign a value of NULL on INSERT, it will get the next auto-increment value.
Also, you should try to avoid:
INSERT INTO people VALUES ("John", "Smith");
and use
INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");
instead. The first version is very fragile — if you ever add, move, or delete columns in your table definition the INSERT will either fail or produce incorrect data (with the values in the wrong columns).
Yes, this is possible. According to the SQLite FAQ:
A column declared INTEGER PRIMARY KEY will autoincrement.
As of today — June 2018
Here is what official SQLite documentation has to say on the subject (bold & italic are mine):
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.
In SQLite, a column with type INTEGER PRIMARY KEY is an alias for the
ROWID (except in WITHOUT ROWID tables) which is always a 64-bit signed
integer.
On an INSERT, if the ROWID or INTEGER PRIMARY KEY column is not
explicitly given a value, then it will be filled automatically with an
unused integer, usually one more than the largest ROWID currently in
use. This is true regardless of whether or not the AUTOINCREMENT
keyword is used.
If the AUTOINCREMENT keyword appears after INTEGER PRIMARY KEY, that
changes the automatic ROWID assignment algorithm to prevent the reuse
of ROWIDs over the lifetime of the database. In other words, the
purpose of AUTOINCREMENT is to prevent the reuse of ROWIDs from
previously deleted rows.
SQLite AUTOINCREMENT is a keyword used for auto incrementing a value of a field in the table. We can auto increment a field value by using AUTOINCREMENT keyword when creating a table with specific column name to auto incrementing it.
The keyword AUTOINCREMENT can be used with INTEGER field only.
Syntax:
The basic usage of AUTOINCREMENT keyword is as follows:
CREATE TABLE table_name(
column1 INTEGER AUTOINCREMENT,
column2 datatype,
column3 datatype,
.....
columnN datatype,
);
For Example See Below:
Consider COMPANY table to be created as follows:
sqlite> CREATE TABLE TB_COMPANY_INFO(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
Now, insert following records into table TB_COMPANY_INFO:
INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );
Now Select the record
SELECT *FROM TB_COMPANY_INFO
ID NAME AGE ADDRESS SALARY
1 Manoj Kumar 40 Meerut,UP,INDIA 200000.00
Have you read this? How do I create an AUTOINCREMENT field.
INSERT INTO people
VALUES (NULL, "John", "Smith");
Always insert NULL as the id.
One should not specify AUTOINCREMENT keyword near PRIMARY KEY.
Example of creating autoincrement primary key and inserting:
$ sqlite3 ex1
CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);
INSERT INTO room(name, home_id) VALUES ('test', 'home id test');
INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');
SELECT * FROM room;
will give:
1|test|home id test
2|test 2|home id test 2
Beside rowid, you can define your own auto increment field but it is not recommended. It is always be better solution when we use rowid that is automatically increased.
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.
Read here for detailed information.
What you do is correct, but the correct syntax for 'auto increment' should be without space:
CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);
(Please also note that I changed your varchars to strings. That's because SQLite internally transforms a varchar into a string, so why bother?)
then your insert should be, in SQL language as standard as possible:
INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');
while it is true that if you omit id it will automatically incremented and assigned, I personally prefer not to rely on automatic mechanisms which could change in the future.
A note on autoincrement: although, as many pointed out, it is not recommended by SQLite people, I do not like the automatic reuse of ids of deleted records if autoincrement is not used. In other words, I like that the id of a deleted record will never, ever appear again.
HTH
I know this answer is a bit late. My purpose for this answer is for everyone's reference should they encounter this type of challenge with SQLite now or in the future and they're having a hard time with it.
Now, looking back at your query, it should be something like this.
CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));
It works on my end. Like so,
Just in case you are working with SQLite, I suggest for you to check out DB Browser for SQLite. Works on different platforms as well.