I need something real simple, that for some reason I am unable to accomplish up to this point.
I have also been unable to Google the answer surprisingly. I need to number the entries in different tables uniquely. I am aware of AUTO INCREMENT in MySQL and that it will be involved. My situation would be as follows:
If I had a table like
Table EXAMPLE
ID - INTEGER
FIRST_NAME - VARCHAR(45)
LAST_NAME - VARCHAR(45)
PHONE - VARCHAR(45)
CITY - VARCHAR(45)
STATE - VARCHAR(45)
ZIP - VARCHAR(45)
This would be the setup for the table where ID is an integer that is auto-incremented every time an entry is inserted into the table. The thing I need is that I do not want to have to account for this field when inserting data into the database. From my understanding this would be a surrogate key, that I can tell the database to automatically increment and I do not have to include it in the INSERT STATEMENT
So, instead of:
INSERT INTO EXAMPLE VALUES (2,'JOHN','SMITH',333-333-3333,'NORTH POLE'....
I can leave out the first ID column and just write something like:
INSERT INTO EXAMPLE VALUES ('JOHN','SMITH'.....etc)
Notice I wouldn't have to define the ID column...
I know this is a very common task to do, but for some reason I cant get to the bottom of it.
I am using MySQL, just to clarify.
Thanks a lot
Make ID auto_increment as shown here. You don't have to provide the value for an auto_increment field when inserting a row, the DB will provide it for you. Note that in this case you still have to use the insert syntax such that you provide the names of the fields, and you'd just leave out the ID field.
This:
INSERT INTO EXAMPLE VALUES ('JOHN','SMITH'.....etc)
...will return a MySQL Error #1136, because the number of columns in the table do not match the number of columns specified in the VALUES clause. So you have two options:
Use NULL to fill in the autoincrement column value. IE:
INSERT INTO EXAMPLE VALUES (NULL, 'JOHN','SMITH'.....etc)
Specify the list of columns for the table that values are being provided for. IE:
INSERT INTO EXAMPLE
(FIRST_NAME, LAST_NAME, PHONE, CITY, STATE, ZIP)
VALUES
('JOHN','SMITH'.....etc)
I don't know about mysql, but in SQL Server you would need to specify the fields you were inser'ing into in the insert (which you should do in all cases anyway as a best practice).
have you tried
insert into Example(field1, field2)
values ('John', 'Smith')
Related
How do I implement a sql command which outputs NULL for salary if it is a voluntary worker?
Here are the tables I created first:
create Table worker (
pid integer references Person,
salary float);
create Table person(
pid integer primary key,
name varchar(30),
adress varchar(30));
Since I'm not sure how to distinguish a normal worker from a voluntary one, I decided to make another table. Unfortunately, I don't know how to insert NULL values for salary for all voluntary workers. That is what I tried out:
create table voluntaryworker(
pid integer references Person,
salary = null);
insert into Person (pid, name, adress) values (1345, anna, 'festreet');
insert into voluntaryworker (pid, salary) values (1345, null);
pid = person ID
Most databases support generated columns. If you really want a salary column in voluntaryworker, then you can use such a column:
create table voluntaryworker (
pid integer references Person,
salary generated always as (cast(null as float))
);
The exact syntax may vary, depending on the database.
Note that having a separate table seems utterly superfluous. Why not just have a flag in the worker table.
Also, representing the salary as a float is quite troublesome. In general, you really should never use floating point representations for monetary amounts. decimal/numeric is much more appropriate for money.
Like others commented, you certainly don't need another table to implement this. All you need is some way to remember whether a worker is voluntary.
To make sure salary sticks to your rule, you can add a CHECK constraint:
CREATE TABLE worker (
pid integer PRIMARY KEY REFERENCES person
, voluntary boolean NOT NULL DEFAULT false
, salary numeric
, CONSTRAINT voluntary_has_no_salary CHECK (NOT voluntary OR salary IS NULL)
);
Meaning: voluntary workers cannot have a nonnull salary.
Alternatively, you might drop the table worker, too, and just add the columns worker_salary and worker_voluntary to table person. (You may need an additional flag worker, or integrate this information in the other two columns ...)
If you are still interested in generated columns (not needed here), see this example with correct syntax and instructions:
Computed / calculated / virtual / derived columns in PostgreSQL
Related:
PostgreSQL: Which Datatype should be used for Currency?
At least insert into voluntaryworker (pid) values (1354); leaves it NULL.
I know this sounds crazy (And if I designed the database I would have done it differently) but I actually want to force a duplicate key on an insert. I'm working with a database that was designed to have columns as 'not null' pk's that have the same value in them for every row. The records keeping software I'm working with is somehow able to insert dups into these columns for every one of its records. I need to copy data from a column in another table into one column on this one. Normally I just would try to insert into that column only, but the pk's are set to 'not null' so I have to put something in them, and the way the table is set up that something has to be the same thing for every record. This should be impossible but the company that made the records keeping software made it work some how. I was wondering if anyone knows how this could be done?
P.S. I know this is normally not a good idea at all. So please just include suggestions for how this could be done regardless of how crazy it is. Thank you.
A SQL Server primary key has to be unique and NOT NULL. So, the column you're seeing duplicate data in cannot be the primary key on it's own. As urlreader suggests, it must be part of a composite primary key with one or more other columns.
How to tell what columns make up the primary key on a table: In Enterprise Manager, expand the table and then expand Columns. The primary key columns will have a "key" symbol next to them. You'll also see "PK" in the column description after, like this:
MyFirstIDColumn (PK, int, not null)
MySecondIDColumn (PK, int, not null)
Once you know which columns make up the primary key, simply ensure that you are inserting a combination of unique data into the columns. So, for my sample table above, that would be:
INSERT INTO MyTable (MyFirstIDColumn, MySecondIDColumn) VALUES (1,1) --SUCCEED
INSERT INTO MyTable (MyFirstIDColumn, MySecondIDColumn) VALUES (1,2) --SUCCEED
INSERT INTO MyTable (MyFirstIDColumn, MySecondIDColumn) VALUES (1,1) --FAIL because of duplicate (1,1)
INSERT INTO MyTable (MyFirstIDColumn, MySecondIDColumn) VALUES (1,3) --SUCCEED
More on primary keys:
http://msdn.microsoft.com/en-us/library/ms191236%28v=sql.105%29.aspx
Say I have 10 million Customer names each associated with one or more Addresses and I want to put the data in a SQL database.
I make a Customer table and an Address table. The Customer table contains an autoincrement primary key. Each Address entry points back to the Customer table with a foreign key.
Now, for each of 10 million records, I have to create a Customer record, insert it into the Customer table, then retrieve it again to get the autoincrement primary key that was assigned to it to use in a new Address entry. 20 million round trips. Ugh.
Is there a better way besides resorting to GUIDs?
(I happen to be using SQLite with SQLAlchemy)
This isn't using SA but an example to illustrate inserting rows in two tables in Sqlite3 and not doing a round trip.
Create a view that joins the two tables, then write an instead of trigger that handles the inserts and then insert into your view. If you want to take this further it shouldn't be hard to modify SA to insert into your view.
create table customer (id integer primary key autoincrement, name text not null);
create table address (id integer primary key autoincrement, customer_id integer references customer not null, street text);
create view customer_view as
select customer.id as customer_id, customer.name, address.id as address_id, address.street
from customer
inner join address on customer.id = address.id;
create trigger customer_view_insert_trg
instead of insert on customer_view begin
insert into customer (name) values (new.name);
insert into address (customer_id, street) values ((select last_insert_rowid()), new.street);
end;
insert into customer_view (name, street) values ('Joe', 'Main Street');
insert into customer_view (name, street) values ('Bill', 'Water Street');
sqlite> select * from customer;
1|Joe
2|Bill
sqlite> select * from address;
1|1|Main Street
2|2|Water Street
If you configure your Customer and Address objects to have a relation between them, you can simply insert them without worrying about the ID. SA knows that they're related and works out the FK details for you.
The careful reader will note that the SA Object Relational Tutorial addresses this use case directly by creating a User object with a related Address. I recognize the OP's actual problem is more complex, but the ORM tutorial seems like a great place to start. SA is a rockin' tool.
Note that you will still need to iterate over your 10M raw data objects, which may mean that your database's bulk-load tools might be a more effective solution, but that's a different approach.
I think this should do it: http://www.sqlite.org/c3ref/last_insert_rowid.html
This routine returns the rowid of the most recent successful INSERT into the database from the database connection in the first argument.
And
If the table has a column of type INTEGER PRIMARY KEY then that column is another alias for the rowid.
Though that's a C/C++ interface function, the function also exists as an SQLite core function (which is, in fact, just a wrapper around the C/C++ one. http://www.sqlite.org/lang_corefunc.html)
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.
In MS Sql Server is easy create autoincrement fields. In my systems I stopped to use autoincrement fields for primary keys, and now I use Guid's. It was awesome, I've got a lot of advantages with that change. But in another non-primary key fields, I really was needing implement a "soft autoincrement". It's because my system is DB independent, so I create the autoinc value programatically in c#.
I would like about solutions for autoincrement fields on databases without autoincrement, what the solution that your use and why? There is some Sql Ansi statement about this? and generating directly from my c#, is a better solution?
PS: I know that select max(id)+1 from table it's not really concurrent friendly...
The mechanism to generate unique id values must not be subject to transaction isolation. This is required for the database to generate a distinct value for each client, better than the trick of SELECT MAX(id)+1 FROM table, which results in a race condition if two clients try to allocate new id values concurrently.
You can't simulate this operation using standard SQL queries (unless you use table locks or serializable transactions). It has to be a mechanism built into the database engine.
ANSI SQL did not describe an operation to generate unique values for surrogate keys until SQL:2003. Before that, there was no standard for auto-incrementing columns, so nearly every brand of RDBMS provided some proprietary solution. Naturally they vary a lot, and there's no way to use them in a simple, database-independent manner.
MySQL has the AUTO_INCREMENT column option, or SERIAL pseudo-datatype which is equivalent to BIGINT UNSIGNED AUTO_INCREMENT;
Microsoft SQL Server has the IDENTITY column option and NEWSEQUENTIALID() which is something between auto-increment and GUID;
Oracle has a SEQUENCE object;
PostgreSQL has a SEQUENCE object, or SERIAL pseudo-datatype which implicitly creates a sequence object according to a naming convention;
InterBase/Firebird has a GENERATOR object which is pretty much like a SEQUENCE in Oracle; Firebird 2.1 supports SEQUENCE too;
SQLite treats any integer declared as your primary key as implicitly auto-incrementing;
DB2 UDB has just about everything: SEQUENCE objects, or you can declare columns with the "GEN_ID" option.
All these mechanisms operate outside transaction isolation, ensuring that concurrent clients get unique values. Also in all cases there is a way to query the most recently generated value for your current session. There has to be, so you can use it to insert rows in a child table.
I think your question is actually quite a good one. However, it is easy to get lost trying to come up with a SQL only solution. In reality you will want the optimization and transaction safety afforded by using the database implementations of the autoincrement types.
If you need to abstract out the implementation of the autoincrement operator, why not create a stored procedure to return your autoincrement value. Most SQL dialects access stored procedures in relatively the same way and it should be more portable. Then you can create database specific autoincrement logic when you create the sproc - eliminating the need to change many statements to be vendor specific.
Done this way, your inserts could be as simple as:
INSERT INTO foo (id, name, rank, serial_number)
VALUES (getNextFooId(), 'bar', 'fooRank', 123456);
Then define getNextFooId() in a database specific way when the database is being initialized.
Most databases that don't have autoincrement fields like SQL Server (I'm thinking Oracle specifically) have sequences where you ask the Sequence for the next number. No matter how many people are requesting numbers at the same time everyone gets a unique number.
The traditional solution is to have a table of ids that look something like this
CREATE TABLE ids (
tablename VARCHAR(32) NOT NULL PRIMARY KEY,
nextid INTEGER
)
which s populated with one row per table when you create the database.
You then do a select to get the next next id for the table you are inserting into, increment it and then update the table with the new id. Obviously, there are locking issues here, but for databases with moderate insert rates it works well. And it is completely portable.
If you need a non-primary-key autoincrement field, a very nice MySQL only solution for creating arbitraty sequences is to use the relatively unknown last_insert_id(expr) function.
If expr is given as an argument to
LAST_INSERT_ID(), the value of the
argument is returned by the function
and is remembered as the next value to
be returned by LAST_INSERT_ID(). This
can be used to simulate sequences...
(from http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_last-insert-id )
Here is an example which demonstrates how a secondary sequence can be kept for numbering comments for each post:
CREATE TABLE `post` (
`id` INT(10) UNSIGNED NOT NULL,
`title` VARCHAR(100) NOT NULL,
`comment_sequence` INT(10) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
CREATE TABLE `comment` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`post_id` INT(10) UNSIGNED NOT NULL,
`sequence` INT(10) UNSIGNED NOT NULL,
`content` TEXT NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO post(id, title) VALUES(1, 'first post');
INSERT INTO post(id, title) VALUES(2, 'second post');
UPDATE post SET comment_sequence=Last_insert_id(comment_sequence+1) WHERE id=1;
INSERT INTO `comment`(post_id, sequence, content) VALUES(1, Last_insert_id(), 'blah');
UPDATE post SET comment_sequence=Last_insert_id(comment_sequence+1) WHERE id=1;
INSERT INTO `comment`(post_id, sequence, content) VALUES(1, Last_insert_id(), 'foo');
UPDATE post SET comment_sequence=Last_insert_id(comment_sequence+1) WHERE id=1;
INSERT INTO `comment`(post_id, sequence, content) VALUES(1, Last_insert_id(), 'bar');
UPDATE post SET comment_sequence=Last_insert_id(comment_sequence+1) WHERE id=2;
INSERT INTO `comment`(post_id, sequence, content) VALUES(2, Last_insert_id(), 'lorem');
UPDATE post SET comment_sequence=Last_insert_id(comment_sequence+1) WHERE id=2;
INSERT INTO `comment`(post_id, sequence, content) VALUES(2, Last_insert_id(), 'ipsum');
SELECT * FROM post;
SELECT * FROM comment;