sqlite: how can I add an autoincrementing id to an existing table? - sql

I would like to add an autoincrementing integer field called uid to an existing table assoc, but it doesn't look like I can do that unless it's a primary key.
I have fields local_id and remote_id which are the existing primary key pair, and I do that so that I can INSERT OR IGNORE INTO assoc so that I don't get duplicate primary keys, but if I have a pair of columns as a primary key, I can't seem to use them as an update (see other SO question).
Could anyone suggest how to restructure the table (and implement that restructuring using ALTER TABLE) so that I can get the behavior I need:
a single autoincrementing key, so I can use that for UPDATEs
a pair of fields local_id and remote_id so that the pair (local_id, remote_id) remains unique in the table

In this case, you could drop the primary key on your existing columns, create the new primary key integer autoincrementing column, then create a UNIQUE index on the other two columns.

Aha, I don't need to -- there's a builtin rowid column.

Related

sqlite text as primary key vs autoincrement integers

I'm currently debating between two strategies to using a text column as a key.
The first one is to simply use the text column itself as a key, as such:
create table a(
key_a text primary key,
)
create table b(
key_b text primary key,
)
create table c(
key_a text,
key_b text,
foreign key("key_a") references a("key_a"),
foreign key("key_b") references b("key_b")
)
I'm concerned that this would result in every key being duplicated, once in a and b and another in c, since text isn't stored inline.
My second approach is to use an autoincrement id on the first two tables as a primary key, and use those ids on table c to refer to them, as such:
create table a(
id_a integer,
key_a text unique,
primary key("id_a" autoincrement)
)
create table b(
id_b integer,
key_b text unique,
primary key("id_a" autoincrement)
)
create table c(
id_a integer,
id_b integer,
foreign key("id_a") references a("id_a"),
foreign key("id_b") references b("id_b")
)
Am I right to be concerned about text duplication in the first case? Or does sqlite somehow intern these and just use an id for both, akin to what the second strategy does?
SQLite does not automatically compress text. So the answer to your question is "no".
Should you use text or an auto-incrementing id as the primary key? This can be a complex question. But happily, the answer is that it doesn't make much difference. That said, there are some considerations:
Integers are of fixed length. In general, fix length keys are slightly more efficient in B-tree indexes than variable length keys.
If the strings are short (like 1 or 2 or 3 characters), then they may be shorter -- or no longer -- than integers.
If you change the string (say, if it is originally misspelled), then using an "artificial" primary key makes this easy: just change the value in one table. Using the string itself as a key can result in lots of updates to lots of tables.
Am I right to be concerned about text duplication in the first case?
Or does sqlite somehow intern these and just use an id for both, akin
to what the second strategy does?
Yes, you are right to be concerned. The text will be duplicated.
Also, even if you did not define an integer primary key in your 1st approach, there is one.
From Rowid Tables:
The PRIMARY KEY of a rowid table (if there is one) is usually not the
true primary key for the table, in the sense that it is not the unique
key used by the underlying B-tree storage engine. The exception to
this rule is when the rowid table declares an INTEGER PRIMARY KEY. In
the exception, the INTEGER PRIMARY KEY becomes an alias for the rowid.
The true primary key for a rowid table (the value that is used as the
key to look up rows in the underlying B-tree storage engine) is the
rowid.
In your 2nd approach actually you are not creating a new column in each of the tables a and b by defining an integer primary key.
What you are doing is aliasing the existing rowid column:
id_a becomes the alias of rowid of the table a
id_b becomes the alias of rowid of the table b.
So, defining these integer primary keys is not more expensive in terms of space in the parent tables.
Although with your 1st approach you can avoid explicit updates in the child tables when you update a value in the parent tables by defining the foreign keys with ON UPDATE CASCADE, your 2nd approach is what I would suggest.
An integer primary key with a value assigned to it by the system and you don't even have to know or worry about it is common practice.
All you have to do is use that primary key and its corresponding foreign keys in the queries that you create to access the parent tables when you want to fetch from them the text values.
For performance (also it is a good db practice) you should stick to numeric/int value for the Primary Key.
As for the second approach, I'm not getting the concept you are after. Could you elaborate more on this?

do not allow duplicates

I am importing data from an access table to SQL. I have a primary key is SQL "quoteID" which obviously doesn't allow duplicates but I'm looking to add that requirement to another field.
Can't seem to find where to set that? perhaps it has to do with the field type??
You can require that a column be unique using a unique constraint or unique index:
alter table t add constraint unq_t_col unique (col);
or:
create unique index unq_t_col on t(col);
Make the field a primary key of the table. Or put an index on that field that enforces unique values.

Sql combine value of two columns as primary key

I have a SQL server table on which I insert account wise data. Same account number should not be repeated on the same day but can be repeated if the date changes.
The customer retrieves the data based on the date and account number.
In short the date + account number is unique and should not be duplicate.
As both are different fields should I concatenate both and create a third field as primary key or there is option of having a primary key on the merge value.
Please guide with the optimum way.
You can create a composite primary key. When you create the table, you can do this sort of thing in SQL Server;
CREATE TABLE TableName (
Field1 varchar(20),
Field2 INT,
PRIMARY KEY (Field1, Field2))
Take a look at this question which helps with each flavour of SQL
How can I define a composite primary key in SQL?
PLEASE HAVE A LOOK, IT WILL CLEAR MOST OF THE DOUBTS !
We can state 2 or more columns combined as a primary key.
In that case every column included in primary key will be called : Composite Key
And mind you Composite keys can never be null !!
Now, first let me show you how to make 2 or more columns as primary key.
create table table_name ( col1 type, col2 type, primary key(col1, col2));
The benefit is :
col1 has value (X) and col2 has value (Y) then no other row can have col1 as (X) and col2 as (Y).
col1, col2 must have some values, they can't be null !!
HOPE THIS HELPS !
Not at all. Just use a primary key constraint:
alter table t add constraint pk_accountnumber_date primary key (accountnumber, date)
You can also include this in the create table statement.
I might suggest, however, that you use an auto-incrementing/identity/serial primary key -- a unique number for each row. Then declare the account number/date combination as a unique key. I prefer such synthetic primary keys for several reasons:
They make it easy to refer to a row in foreign key relationships.
They show the insert order into the table, so you can readily see the last inserted rows.
They make it simple to identify a single row for updates and deletes.
They hide the "id" information of the row from referring tables and applications.
The alternative is to have a PK which is an autoincrementing number and then put a unique unique index on the natural key. In this way uniqueness is preserved but you have the fastest possible joining to any child tables. If the table will not ever have child tables, the composite PK is a good idea. If there will be many child tables, this is could be a better choice.

SQL Primary Key Duplicate Values

I have a table with 2 primary key columns : ID and StudentID.
ID column is set to isIdentity = Yes with auto increment.
I've tested it multiple times before, but for some reason this time, when I insert a duplicate value on StudentID, it does not throw the error but instead added it on to the database. 2 of the same values are displayed when I show the table data.
What can be the problem here?
You have a compound primary key on ID and StudentID. That means you the combination of ID and StudentID together must be unique. Since ID is an identity column that combination of ID and StudentID will always be unique (because ID is already unique on its own).
You can change the primary key to be on ID only. Then you can add a unique index on StudentID. For example:
create unique index idx_studentID on yourTable(StudentID)
That will insure that the StudentID column, in fact, contains only unique values.
It seems like you may not actually need ID column, but that's a little wider discussion than your original question.
You can't have 2 "primary keys". You can have a compound primary key (meaning the combination needs to be unique, which is what it sounds like you have now. Or, You can have one "primary" key and one "unique" constraint which is what it sounds like you want.
You cannot have 2 Primary Keys. You can have multiple Unique Keys if needed, which should help you in your case. Make sure to go back to your table creation and double check which column is your Primary Key and work from there.
Do not mix up identity, primary key and unique key.
Any table can have identity key which you can setup on table. Here seed can be say 1, then increment it by 1. So incremental order will like 1,2,3...and so on.
Primary key, one can define on specific column of the table. Identity key can be used as primary key. But you can have identity column as well primary key on same table. Primary key is one and only for the table.So if you are treating identity as primary key, then you will have no further table column as primary key.
Unique key, can be more than one column with your table.
While fetching rows from table data, if you provide combination of identity key, primary key and unique key then search will be fastest
During my first response, I have mentioned that one can generate identity column by soft coding and it will not be treated as primary key.Following is syntax one can use while creating table.
1] If one wish to set identity column as primary key
--id int identity(1,1) primary key
2] If one doesn't wish to set identity column as primary key and still wish
to us identity column then donot us word primary key for identity column.
--id int identity(1,1)
In this 2] case scenario, one may create primary key on other table column.

MySQL Lookup table and id/keys

Hoping someone can shed some light on this: Do lookup tables need their own ID?
For example, say I have:
Table users: user_id, username
Table categories: category_id, category_name
Table users_categories: user_id, category_id
Would each row in "users_categories" need an additional ID field? What would the primary key of said table be? Thanks.
You have a choice. The primary key can be either:
A new, otherwise meaningless INTEGER column.
A key made up of both user_id and category_id.
I prefer the first solution but I think you'll find a majority of programmers here prefer the second.
You could create a composite key that uses the both keys
Normally if there is no suitable key to be found in a table you want to create a either a composite key, made up of 2 or more fields,
ex:
Code below found here
CREATE TABLE topic_replies (
topic_id int unsigned not null,
id int unsigned not null auto_increment,
user_id int unsigned not null,
message text not null,
PRIMARY KEY(topic_id, id));
therefor in your case you could add code that does the following:
ALTER TABLE users_categories ADD PRIMARY KEY (user_id, category_id);
therefor once you want to reference a certain field all you would need is to pass the two PKs from your other table, however to link them they need to each be coded as a foreign key.
ALTER TABLE users_categories ADD CONSTRAINT fk_1 FOREIGN KEY (category_id) REFERENCES categories (category_id);
but if you want to create a new primary key in your users_categories table that is an option. Just know that its not always neccessary.
If your users_categories table has a unique primary key over (user_id, category_id), then - no, not necessarily.
Only if you
want to refer to single rows of that table from someplace else easily
have more than one equal user_id, category_id combination
you could benefit from a separate ID field.
Every table needs a primary key and unique ID in SQL no matter what. Just make it users_categories_id, you technically never have to use it but it has to be there.