prevent autoincrementing integer primary key? - sql

I have a sqlite table (sqlite version 3.7.3) where nulls inserted into the primary key column are being undesirably auto-incremented:
sqlite> CREATE TABLE foo(bar INTEGER NOT NULL PRIMARY KEY);
sqlite> INSERT INTO foo(bar) VALUES(NULL);
sqlite> SELECT * FROM foo;
1
In the sqlite docs, it shows that adding the AUTOINCREMENT keyword to the column should create this behavior, but there doesn't appear to be a keyword to prevent the auto incrementing...
I also found that I can build sqlite with the SQLITE_OMIT_AUTOINCREMENT compile option, but I don't want to disable the behavior globally, just for this particular column.
Interestingly, if I don't include the PRIMARY KEY constraint, I get the desired behavior:
sqlite> CREATE TABLE FOO(bar integer NOT NULL);
sqlite> INSERT INTO FOO(bar) VALUES(NULL);
SQL error: foo.bar may not be NULL
How can I define the table so that NULL values are rejected and keep the primary key constraint?

Autoincrement behavior applies only to columns declared as INTEGER PRIMARY KEY. So the easiest ways to disable it are:
Declare the column as UNIQUE instead of PRIMARY KEY.
Declare the column type as INT instead of INTEGER.
Note that either one will give you a column with integer affinity instead of being constrained to contain only integers.

One way to disable autoincrement (outside of recreating the table) when you need to insert data is to use the import tool in sqlite3:
If you have a table like this:
CREATE TABLE [table1] ( [ID] integer PRIMARY KEY AUTOINCREMENT NOT NULL, [col1] TEXT);
If you run the import command on it with your data file:
ID col1
10 abc
20 def
import myfile.txt table1
It will import the rows, and it will disregard the autoincrement feature.

Related

How to make reference to sqlite_master's field?

It's possible make reference to field name of sqlite_master table? Something like this:
CREATE TABLE metadata (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT REFERENCES sqlite_master (name) ON DELETE CASCADE
UNIQUE
NOT NULL,
description TEXT
);
When I'm trying to execute this script then SQLiteStudio return error message SQL logic error. I need create table with human-readable description of tables. I want make field name of service table sqlite_master as foreign key in my table.
Here's what's happening:
A column used as a parent key needs to either be the parent table's primary key, or have an unique index/constraint on it. The sqlite_master table has no such thing for the name column (And you can't add an index on it), thus it can't be used. I'm not sure why you're getting a logic error on table creation instead of a foreign key mismatch error at time of insert like you do in the same situation on normal tables, though:
sqlite> pragma foreign_keys = on;
sqlite> create table parent(id integer primary key, name text not null);
sqlite> insert into parent(name) values ('Bob');
sqlite> create table child(id integer primary key, name text references parent(name));
sqlite> insert into child(name) values ('Bob');
Error: foreign key mismatch - "child" referencing "parent"
sqlite> create unique index parent_idx_name on parent(name);
sqlite> insert into child(name) values ('Bob');
sqlite>
If foreign key enforcement is disabled like it is by default, what you're trying will be accepted, it just doesn't do anything and will raise errors if you turn on FKs later and try to do stuff with the table.

Why can't you use SQLite ROWID as a Primary key?

This does not execute:
create table TestTable (name text, age integer, primary key (ROWID))
The error message is:
11-23 11:05:05.298: ERROR/Database(31335): Failure 1 (table TestTable has no column named ROWID) on 0x2ab378 when preparing 'create table TestTable (name text, age integer, primary key (ROWID))'.
However, after the TestTable is created, this prepares and executes just fine:
create table TestTable (name text, age integer);
insert into TestTable (name, age) values ('Styler', 27);
select * from TestTable where ROWID=1;
I could potentially see ROWID as being a solution to needing an auto-increment primary key and foreign key which are never going to be used as populated as data on the application layer. Since ROWID is hidden from select result sets by default, it would have been nice to associate this with the primary key while keeping it hidden from the application logic. OracleBlog: ROWNUM and ROWID say this is impossible and inadvisable, but doesn't provide much explanation other than that.
So, since the answer to 'is this possible' is definitely no/inadvisable, the question is more or less 'why not'?
Summary from SQLite.org:
In SQLite, table rows normally have a 64-bit signed integer ROWID
which is unique among all rows in the same table. (WITHOUT ROWID
tables are the exception.)
If a table contains a column of type INTEGER PRIMARY KEY, then that
column becomes an alias for the ROWID. You can then access the ROWID
using any of four different names, the original three names (ROWID,
_ROWID_, or OID) or the name given to the INTEGER PRIMARY KEY
column. All these names are aliases for one another and work equally
well in any context.
Just use it as the primary key.

SQLite: autoincrement primary key questions

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.

SQL Server, can't insert null into primary key field?

I'm about ready to rip my hair out on this one. I'm fairly new to MS SQL, and haven't seen a similar post anywhere.
When I try to do a statement like this:
INSERT INTO qcRawMatTestCharacteristic
VALUES(NULL, 1,1,1,1,1,1,1,'','','', GETDATE(), 1)
I get the following:
Cannot insert the value NULL into
column 'iRawMatTestCharacteristicId',
table
'Intranet.dbo.qcRawMatTestCharacteristic';
column does not allow nulls. INSERT
fails.
I understand the error, but the null value is for my my primary field with an int data type.
Any ideas!?
Primary keys in any relational database are not allowed to be NULL - it's one of the main, fundamental characteristics of a primary key.
See: SQL by Design: how to Choose the primary key
Never Null
No primary key value can be null, nor can you do anything to
render the primary key null. This is
an inviolate rule of the relational
model as supported by ANSI, of
relational database management system
(RDBMS) design, and of SQL Server.
UPDATE: ok, so you want an "auto-increment" primary key in SQL Server.
You need to define it as an INT IDENTITY in your CREATE TABLE statement:
CREATE TABLE dbo.YourTable(ID INT IDENTITY, col1 INT, ..., colN INT)
and then when you do an INSERT, you need to explicitly specify the columns to insert, but just don't specify the "ID" column in that list - then SQL Server will handle finding the proper value automagically:
INSERT INTO dbo.YourTable(col1, col2, ..., colN) -- anything **except** `ID`
VALUES(va1l, val2, ..., valN)
If you want to do this after having created the table already, you can do so in the SQL Server Management Studio's table designer:
Primary Key fields cannot contain null values in MS SQL. If you want to populate a SQL table and dont know what to enter for a integer based primary key field then set the pk to an Identity field. Also when specifying Insert statements its wise to use the column mapping portion of the insert statment for example:
Insert into (field1, field2, field3)
values
(value1, value2, value3)
The reason for this is it insures that the column order is what you developed for as a SQL administrator can modify column order. It also allows you to insert a row with an identity Primary key with out specifying the value of the Primary Key Example
CREATE TABLE [dbo].[foo](
[fooid] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NULL,
CONSTRAINT [PK_foo] PRIMARY KEY
(
[fooid] ASC
)
now my insert statement is simple
Insert into foo (name)
values
("John")
the result in the table would be
1, "John"
You probably don't have (you forgot to add) autoincrement set on your integer primary key.
Primary keys shouldnt accept null value.Why you are inserting null values to a primary key field ?Primary key field should have a non-nullable,unique value which will make each of your record in the table unique
you can use 0 instead of null for only 1 unique row, null is not possible for PK. Or you can omit PK and use and auto increament PK field
Assuming you have an autoincrement field for your primary Key you'll need to include the field list on your insert and not put a value for that field e.g.
INSERT INTO qcRawMatTestCharacteristic
(Answer1,Answer2,...SomeDateField)
VALUES(1,1,1,1,1,1,1,'','','', GETDATE(), 1)
I'm assuming your real issue is that you're not sure how to write an insert statement so that the PK is auto populated correct? You need to name the fields you're setting values for, it looks like you're trying to set all of them but just exclude the PK field like so:
INSERT INTO someTable
(fieldName1, fieldName2)
VALUES(1,1)
Where sometable is a table with three fields. PK, fieldName1, and fieldName2. You also need to make sure that the identity property on the PK field is set to true.
if you have an identity column, you don't need to specify it in the insert statement.
INSERT INTO qcRawMatTestCharacteristic
VALUES(1,1,1,1,1,1,1,'','','', GETDATE(), 1)
However, if you have a primary key that isn't an identity column, then you do need to specify it, because otherwise it'll try to insert a null and primary keys by default are non-nullable.

Altering SQLite column type and adding PK constraint

How to change the type of a column in a SQLite table?
I've got:
CREATE TABLE table(
id INTEGER,
salt TEXT NOT NULL UNIQUE,
step INT,
insert_date TIMESTAMP
);
I'd like to change salt's type to just TEXT and id's type to INTEGER PRIMARY KEY.
Below is an excerpt from the SQLite manual discussing the ALTER TABLE command (see URL: SQLite Alter Table):
SQLite supports a limited subset of
ALTER TABLE. The ALTER TABLE command
in SQLite allows the user to rename a
table or to add a new column to an
existing table. It is not possible to
rename a colum, remove a column, or
add or remove constraints from a
table.
As the manual states, it is not possible to modify a column's type or constraints, such as converting NULL to NOT NULL. However, there is a work around by
copying the old table to a temporary table,
creating a new table defined as desired, and
copying the data from the temporary table to the new table.
To give credit where credit is due, I learned this from the discussion on Issue #1 of hakanw's django-email-usernames project on bitbucket.org.
CREATE TABLE test_table(
id INTEGER,
salt TEXT NOT NULL UNIQUE,
step INT,
insert_date TIMESTAMP
);
ALTER TABLE test_table RENAME TO test_table_temp;
CREATE TABLE test_table(
id INTEGER PRIMARY KEY,
salt TEXT,
step INT,
insert_date TIMESTAMP
);
INSERT INTO test_table SELECT * FROM test_table_temp;
DROP TABLE test_table_temp;
Notes
I used the table name test_table since SQLite will generate an error if you try to name a table as table.
The INSERT INTO command will fail if your data does not conform to the new table constraints. For instance, if the original test_table contains two id fields with the same integer, you will receive an "SQL error: PRIMARY KEY must be unique" when you execute the "INSERT INTO test_table SELECT * FROM test_table_temp;" command.
For all testing, I used SQLite version 3.4.0 as included as part of Python 2.6.2 running on my 13" Unibody MacBook with Mac OS X 10.5.7.
Since RDBMS is not specified, these are DB2 queries:
Make ID as primary key:
ALTER TABLE table
ADD CONSTRAINT pk_id
PRIMARY KEY (id)
Make salt as not UNIQUE:
ALTER TABLE table
DROP UNIQUE <salt-unique-constraint-name>
Make salt nullable:
ALTER TABLE table
ALTER COLUMN salt DROP NOT NULL
You will need to do a reorg after drop not null. This is to be done from the command prompt.
reorg table <tableName>
In this case you can make salt to nullable and remove unique constraint. Also If id column does not contain any null or duplicate values you can safely make it primary key using sql server management studio. below is the screen shot. hope it makes it clearer:
alt text http://img265.imageshack.us/img265/7418/91573473.png
or use following sql:
alter table <TableName> modify salt text null
alter table <TableName> drop constraint <Unique Constraint Name>
alter table <TableName> modify id int not null
alter table <TableName> add constraint pk<Table>d primary key (id)