MySQL: Increment numerical PK from one point forward - primary-key

I have a table with a primary key with subsequent values 1,2,3,4,... 1035
I want to insert a new value somewhere in this sequence and increment all values above the said value (actually, the order would be the other way round).
Obviously, I get an error with a simple statement like
UPDATE Table
SET primary_id=primary_id+1
WHERE primary_id > 501
because primary_id 502 is incremented to 503, and 503 already exists.
It seems a very basic question, but I don't remember how to do it.
The table is in MySQL, but I don't think this really matters.

First, take a backup of your table, like this:
CREATE TABLE backup LIKE table;
INSERT INTO backup SELECT * FROM table;
Then, you can run the following queries:
-- remove auto_increment attribute and unique constraint
ALTER TABLE table MODIFY id INT NOT NULL, DROP PRIMARY KEY;
-- your original query
UPDATE table SET id = (id+1) WHERE id > 501;
-- re-add the primary key
ALTER TABLE table MODIFY id INT NOT NULL PRIMARY KEY AUTO_INCREMENT;
If results are OK, remove the backup:
DROP TABLE backup;

Related

Oracle sql constraint questions

I'm having problems with creating a oracle sql script. How do I create these two constraints?
If VID is null then FID has to be null as well (VID = null -> FID = null)
There has to be exactly one row where VID is null which also means that FID has to be null because of 1.
Here is what I have so far:
create table Employee(
Id int primary key,
Name varchar(15) not null,
VID int,
FID int
);
Employee
You can come very close to what you want without a trigger.
You can use a check constraint for the first:
alter table Employee add constraint chk_vid_fid
check (vid is not null or fid is null);
You can do the second using a unique constraint:
create unique index unq_Employee_vid on
Employee(case when vid is null then -1 else id end);
This formulation assumes that id is non-negative, as most ids usually are. If you do use the full range of integer values, then I would be explicit with a string:
create unique index unq_Employee_vid on
Employee(case when vid is null then 'null vid' else cast(id as varchar2(255)) end);
This guarantees at most one row where vid is null, rather than exactly one row. You cannot easily have a constraint that guarantees that exactly one row has a value, because empty tables do not match the condition -- and tables are empty when they are created.
Here is how you can enforce your requirement - to have exactly one row with VID is NULL. As I said in my Comment under your original question (and Gordon said as well in his accepted Answer), you cannot do this just with constraints. However, you can do it with a materialized view. Note that you must create the MV with refresh fast on commit, and that requires certain things for the materialized view log on the base table.
Also: If you try everything exactly as written, the constraint on the MV will fail (of course, because the base table will be empty, so there will be no row where VID is NULL). Add rows to the base table, of which exactly one has NULL for VID, then commit the transaction, and then execute the alter table command to add the constraint to the MV. From that point on, a transaction on the base table (consisting of one or more insert, delete, update or merge statements, followed by one commit) will go through if and only if it leaves exactly one row with NULL in the VID column.
One oddity to keep in mind: even though there is an ALTER MATERIALIZED VIEW statement in Oracle SQL, to add a constraint on a MV we must use the ALTER TABLE statement (with the MV's name), not ALTER MATERIALIZED VIEW.
Note that I used the name t_Employee for the base table, as I already had a table EMPLOYEE and I don't want to mess with my existing objects.
create table t_Employee(
Id int primary key,
Name varchar(15) not null,
VID int,
FID int
);
alter table t_Employee add constraint chk_vid_fid
check (vid is not null or fid is null)
;
create materialized view log on t_Employee
with rowid
(VID)
including new values
;
create materialized view mv_Employee
refresh fast on commit
as select count(*) ct
from t_Employee
where VID is null
;
alter table mv_Employee add constraint chk_vid_ct
check (ct = 1)
;

How to change the primary key value in sql server?

I am using SQL server 2014.
In my table, I set primary key for the column.The primary key value starts from 1. I want to change it to start from 0. How can I achieve this?
If the table is empty, the easiest thing to do would be to drop the table and recreate it with an identity seed of 0 like GuidoG did. If the table has data, changing the primary key to a 0 (like Intern87 mentions) would be a bad idea because after it inserts a row with a key of 0 the next key would be 1 which would probably already be in the table and therefore would cause further inserts to fail with a primary key duplication error.
So if you have existing data but you MUST have data with a key of 0, I would probably just do an identity insert with row 0. Do this with the following
SET IDENTITY_INSERT mytable ON;
INSERT INTO mytable (id, col1, col2, etc..)
VALUES (0, 'col1data','col2data', etc..);
SET IDENTITY_INSERT mytable OFF;
just make sure to run all of that at once because once you turn identity insert on then other inserts may fail till you turn it off.
this creates a table where the autoinc fields starts with 0 in stead of 1
Also it is best to name your primary key
CREATE TABLE myTable
(
id int IDENTITY(0,1),
othercolumn int,
and so on...
constraint PK_myTableID primary key (id)
)
If however you want to do this with an existing table than your best option is to use Element Zero's anwser
You may be able to reseed it;
DBCC CHECKIDENT ('TableName', RESEED, 0);
GO

How to add a PK to an existing table in DB2?

I am facing one problem. I have a table already create in DB2.
CREATE TABLE "DDL12"
(
"D4_1" decimal(10,0),
"D4_2" decimal(10,0),
);
I am trying to create a PK on this table as :-
ALTER TABLE "DDL12" ADD CONSTRAINT "Key4" PRIMARY KEY ("D4_1");
But while running the command, I am getting the error saying D4_1 is NULLABLE.
Now, how can I create a PK on this table?
Thanks
Yes, this is due the fact, that your database "could have" rows having NULL value in that non PK column right now.
So first set the column to NOT NULL (+ make sure having a unique value in all rows) and then set the primary key with the command above.
You can change a column to not NULL like this:
ALTER TABLE "DDL12"
MODIFY "D4_1" decimal(10,0) NOT NULL;

How reorder primary key?

I have deleted one row(row 20) in my "table category" ,please let me know that how can i reorder the catid (primary key)? at this time it is 21 after 19.
Thanks
You cannot. The closest you can get is truncate table, which will drop the table and recreate it, which means you lose all data in it, and the ID counter is reset to 0. Other than that, ID will always increment by one from the last inserted record, no matter if that record still exists or not. You can write a query to fix all your current IDs, of course, but upon next insert, it'll still create a new gap. More to the point: if a sequential ordering without gaps is what you want, auto incremental ID is not the proper way to achieve that. Add another int field where you manually keep track of this ordering.
If you care enough about your primary key values that such a value is unwanted, you shouldn't be using auto-number primary keys in the first place.
The whole point with a auto-number key is that you say "As long as the key is unique, I don't really care about its value."
Don't mess with the primary keys. They should never change and you should not use them in your app for anything but joining tables.
Add a new column if you need a gapless index and update this column accordingly when you do inserts/removes. This might sound like useless work for you right now, but it will save you a lot of pain later.
Try this:
UPDATE tbl SET catid = (SELECT COUNT(*) FROM tbl t WHERE t.catid <= tbl.catid);
You might also want to rethink / redesign. Renumbering the entire table when you delete a row doesn't seem likely to be either practical or necessary.
Actually you can.
If your rows have unique enough data and you are using PHPmyAdmin
Delete the Column with the Primary ID
Read the Column with Primary Key and Auto Increment enabled.
What do you mean by reordering primary key? If you are saying that you want the primary key to take 20 instead of 21, then I afraid you can't do that straightaway.
All you can do, is to drop the primary key constraint, then change the 21 to 20, and reapply back the primary key constraint
David is right about not using primary key for indexing and such.
If you'll just have to change a particular primary key value once (I've done it sometimes during migration) you could of course set identity_insert on and copy the row with a insert select and then delete the original one.
For recreating a sort order or an column used as an index in your application you could use the following stored procedure:
CREATE PROCEDURE [dbo].[OrganizeOrderConfirmationMessages]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sortOrder INT;
SET #sortOrder = 0;
-- // Create temporary table
CREATE TABLE #IDs(ID INT, SortOrder INT)
-- // Insert IDs in order according to current SortOrder
INSERT INTO #IDs SELECT ocm.ID, 0 FROM OrderConfirmationMessages ocm ORDER BY ocm.SortOrder ASC
-- // Update SortOrders
UPDATE #IDs SET SortOrder = #sortOrder, #sortOrder = #sortOrder + 10
-- // Update the "real" values with data from #IDs
UPDATE OrderConfirmationMessages SET SortOrder = x2.SortOrder
FROM #IDs x2 WHERE OrderConfirmationMessages.ID = x2.ID
END
Results:
An example of SortOrders will go from 1,2,5,7,10,24,36 to 10,20,30,40,50,60,70
You should drop the 'catid' field and then create it again, set it as primary and check the Auto Increment checkbox, it will add the new field and fill the numbers.
First drop the primary key column from your table and run this syntax in your phpmyadmin sql section-
ALTER TABLE 'your_tablename' ADD 'column_name' BIGINT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY
('column_name' (10));
This will automatically arrange the column in numbers from 0, 1 and so on.
try this:
SET #var:=0;
UPDATE `table` SET `id`=(#var:=#var+1);
ALTER TABLE `table` AUTO_INCREMENT=1;
In postgres, you can do this where number of records < 300:
update schema.tbl1
set tbl_id = tbl_id + 300;
alter sequence schema.tbl1_id_seq
restart with 1;
insert into schema.tbl1
select nextval('schema.tbl1_id_seq'),
column2,
column3
from schema.tbl1;
delete from schema.tbl1
where tbl1_id > 300;

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)