Alter column length with or without data in table - database

Its about ORACLE (PL/SQL) script. I am not very familiar with databse to be honest.
I want to alter the length of a string in a column from 30 to 60. It is not null column.
If the table is empty and I run following script then it works:
alter table [TABLE_NAME] add ( NEW_COLUMN NVARCHAR2(60) DEFAULT 'null' NOT NULL );
/
alter table [TABLE_NAME] DROP CONSTRAINT PK_[TABLE_NAME];
/
begin
for rec in ( select * from [TABLE_NAME] )
loop
update [TABLE_NAME] set NEW_COLUMN =rec.OLD_COLUMN where Name_ID=rec.Name_ID;
end loop;
end;
/
alter table [TABLE_NAME] drop column OLD_COLUMN;
/
alter table [TABLE_NAME] rename column NEW_COLUMN to OLD_COLUMN;
/
alter table [TABLE_NAME] add CONSTRAINT PK_[TABLE_NAME] PRIMARY KEY(Name_ID);
/
But if the table has values then this script does not work.
It gives error: Cannot drop constraint - nonexistent constraint
However, if I remove lines about constraints (second and second last) then it works.
Now I don’t know if the table will be empty or it will have data so I need a script that can work in both the situations. Can anyone help please?
Following script for creating table:
CREATE TABLE TABLE_NAME
(
Name_ID NVARCHAR2(7) NOT NULL,
OLD_COLUMN NVARCHAR2(30) NOT NULL,
CONSTRAINT PK_TABLE_NAME PRIMARY KEY(Name_ID, OLD_COLUMN)
)
/
So while creating table it puts the primary key constraints but while updating table it drops this constraints somehow. I am simplyfying the sitation here. The tables are updates through java code. What I need to do is make a script that work in both situations - with data or just after creating table and modifying the column.

The following script works for me, regardless of whether the insert statement is present or not (ie. the table has or has not data):
CREATE TABLE TABLE_NAME
(
Name_ID NVARCHAR2(7) NOT NULL,
OLD_COLUMN NVARCHAR2(30) NOT NULL,
CONSTRAINT PK_TABLE_NAME PRIMARY KEY(Name_ID, OLD_COLUMN)
);
insert into table_name (name_id, old_column)
values ('test', 'test_old_col');
commit;
alter table table_name add (new_column nvarchar2(60) default 'null' not null);
update table_name set new_column = old_column;
commit;
alter table table_name drop constraint PK_TABLE_NAME;
alter table table_name drop column old_column;
alter table table_name rename column new_column to old_column;
alter table TABLE_NAME add CONSTRAINT PK_TABLE_NAME PRIMARY KEY(Name_ID, old_column);
drop table table_name;
I have assumed that you meant to recreate the primary key with the old_column in it, otherwise you would be unable to recreate it if there are any duplicate values present in the name_id column.

As an alternative, you can save the old data and create a new table with new parameters. Then insert the old values.
In SQL Server Management Studio:
"your database" => task => generatescripts => select specific database object => "your table" => advanced => types of data to script - schema and data => generate

Related

SQL Server 8111 - but column is NOT NULLABLE

I want to add a primary key constraint to an existing column on an existing table that contains data. The column is not nullable.
However, when I call
alter table mytable add primary key (mycolumn)
I get an 8111:
Msg 8111, Level 16, State 1, Line 2 Cannot define PRIMARY KEY
constraint on nullable column in table 'mytable'
Even if I call both instructions in a row:
alter table mytable alter column mycolumn INT NOT NULL;
alter table mytable add primary key (mycolumn)
I still get an 8111
- and the column description in SQL Server Management Studio confirms, that mycolumn is set to NOT NULL
What can I do this?
You need to separate your batches. It would be best to include the schema name as well.
alter table dbo.mytable alter column mycolumn INT NOT NULL;
go
alter table dbo.mytable add primary key (mycolumn);
rextester demo: http://rextester.com/TZLEWP56616

Set auto id to primary key column [duplicate]

This question already has answers here:
How to add identity to the column in SQL Server?
(4 answers)
Closed 8 years ago.
I have a table and primary key is already set to that table and now I want that column to be autoincrement. Table has many records. Is it possible? or which one is fastest way to do that?
I think you have to make some effort for this as you cannot create identity column on existing column. However you may have a workaround for this like first try this to add a new column having identity field:
ALTER TABLE dbo.Table_name
ADD ID INT IDENTITY
and then make your ID as primary key like this:
ALTER TABLE dbo.Table_name
ADD CONSTRAINT PK_YourTable
PRIMARY KEY(ID)
And yes you have to remove the old dependencies before performing the above steps like this:
ALTER TABLE Table_name
DROP CONSTRAINT PK_Table1_Col1
EDIT:-
From the source:
We can use ALTER TABLE...SWITCH to work around this by only modifying metadata. See Books Online for restrictions on using the SWITCH method presented below. The process is practically instant even for the largest tables.
USE tempdb;
GO
-- A table with an identity column
CREATE TABLE dbo.Source (row_id INTEGER IDENTITY PRIMARY KEY NOT NULL, data SQL_VARIANT NULL);
GO
-- Some sample data
INSERT dbo.Source (data)
VALUES (CONVERT(SQL_VARIANT, 4)),
(CONVERT(SQL_VARIANT, 'X')),
(CONVERT(SQL_VARIANT, {d '2009-11-07'})),
(CONVERT(SQL_VARIANT, N'áéíóú'));
GO
-- Remove the identity property
BEGIN TRY;
-- All or nothing
BEGIN TRANSACTION;
-- A table with the same structure as the one with the identity column,
-- but without the identity property
CREATE TABLE dbo.Destination (row_id INTEGER PRIMARY KEY NOT NULL, data SQL_VARIANT NULL);
-- Metadata switch
ALTER TABLE dbo.Source SWITCH TO dbo.Destination;
-- Drop the old object, which now contains no data
DROP TABLE dbo.Source;
-- Rename the new object to make it look like the old one
EXECUTE sp_rename N'dbo.Destination', N'Source', 'OBJECT';
-- Success
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Bugger!
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
PRINT ERROR_MESSAGE();
END CATCH;
GO
-- Test the the identity property has indeed gone
INSERT dbo.Source (row_id, data)
VALUES (5, CONVERT(SQL_VARIANT, N'This works!'))
SELECT row_id,
data
FROM dbo.Source;
GO
-- Tidy up
DROP TABLE dbo.Source;

Add primary key column in SQL table

I am student of RDBMS.
I have very basic question let say I have one existing Table in SQL server. What will be script to alter table.
Drop Column 'RowId' if exist.
Drop contraint if exist.
Add one new column 'RowId' into table.
Make this column as primary key.
Autoincrement type int.
In SQL Server 2005 or newer, you could use this script:
-- drop PK constraint if it exists
IF EXISTS (SELECT * FROM sys.key_constraints WHERE type = 'PK' AND parent_object_id = OBJECT_ID('dbo.YourTable') AND Name = 'PK_YourTable')
ALTER TABLE dbo.YourTable
DROP CONSTRAINT PK_YourTable
GO
-- drop column if it already exists
IF EXISTS (SELECT * FROM sys.columns WHERE Name = 'RowId' AND object_id = OBJECT_ID('dbo.YourTable'))
ALTER TABLE dbo.YourTable DROP COLUMN RowId
GO
-- add new "RowId" column, make it IDENTITY (= auto-incrementing)
ALTER TABLE dbo.YourTable
ADD RowId INT IDENTITY(1,1)
GO
-- add new primary key constraint on new column
ALTER TABLE dbo.YourTable
ADD CONSTRAINT PK_YourTable
PRIMARY KEY CLUSTERED (RowId)
GO
Of course, this script may still fail, if other tables are referencing this dbo.YourTable using foreign key constraints onto the pre-existing RowId column...
Update: and of course, anywhere I use dbo.YourTable or PK_YourTable, you have to replace those placeholder with the actual table / constraint names from your own database (you didn't mention what they were, in your question.....)
Note: this answer was added before questions update
Add new column (note: you can only have one IDENTITY column per table)
Drop old primary key
Add new primary key
Drop old column if needed
Sample script:
CREATE TABLE whatever (
OldPKColumn uniqueidentifier NOT NULL,
CONSTRAINT PK_whatever PRIMARY KEY (OldPKColumn)
)
ALTER TABLE whatever
ADD RowId int NOT NULL IDENTITY (1,1);
ALTER TABLE whatever
DROP CONSTRAINT PK_whatever;
ALTER TABLE whatever WITH CHECK
ADD CONSTRAINT PK_whatever PRIMARY KEY CLUSTERED (RowId);
ALTER TABLE whatever
DROP COLUMN oldPKcolumn;
And a random thought... are you trying to reset an IDENTITY column?
If so, then use DBCC CHECKIDENT
Just a comment to improve these great answers (can't use comments yet - I'm one reputation point away from that privilege) and as future reference for myself:
A new IDENTITY (autonumber) column can be added and made the primary key in a single statement as well:
ALTER TABLE [TableName] ADD [ColumnName] int IDENTITY PRIMARY KEY;
I prefer not to bother with constraint names when it doesn't help.
You can specify seed (and increment) values between parantheses after the IDENTITY keyword.

ALTER TABLE constraint problem

I'm trying to run the following SQL statement:
IF OBJECT_ID('MyTable') IS NOT NULL
DROP TABLE MyTable
SELECT
a.UserId
INTO
MyTable
FROM
UsersTable a
WHERE
a.UserId='12359670-1DC9-4A0A-8AE5-29B664C1A57E'
ALTER TABLE MyTable ALTER COLUMN UserId UNIQUEIDENTIFIER NOT NULL
ALTER TABLE MyTable ADD PRIMARY KEY(UserId)
However, I get the following error:
Cannot define PRIMARY KEY constraint on nullable column in table 'MyTable'.
Any ideas?
This assumes SQL Server based on UNIQUEIDENTIFIER
Put a GO between (or relevant batch separator if not SQL Server)
....
ALTER TABLE MyTable ALTER COLUMN UserId UNIQUEIDENTIFIER NOT NULL
GO
ALTER TABLE MyTable ADD PRIMARY KEY(UserId)
At batch compile time, the column is nullable. So break up the batches.
SQL isn't a line by line procedural language
You'll have to do this in a stored procedure
ALTER TABLE MyTable ALTER COLUMN UserId UNIQUEIDENTIFIER NOT NULL
EXEC('ALTER TABLE MyTable ADD PRIMARY KEY(UserId)')
Found a solution.
I'm using the following statement:
EXEC sp_ExecuteSQL N'ALTER TABLE MyTable ALTER COLUMN UserId UNIQUEIDENTIFIER NOT NULL'
EXEC sp_ExecuteSQL N'ALTER TABLE MyTable ADD PRIMARY KEY(UserId)'
You don't need dynamic SQL. Just create the table and the key first.
CREATE TABLE MyTable (UserId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY);
INSERT INTO MyTable (UserId)
SELECT UserId
FROM UsersTable
WHERE UserId='12359670-1DC9-4A0A-8AE5-29B664C1A57E';

SQL Server, How to set auto increment after creating a table without data loss?

I have a table table1 in SQL server 2008 and it has records in it.
I want the primary key table1_Sno column to be an auto-incrementing column. Can this be done without any data transfer or cloning of table?
I know that I can use ALTER TABLE to add an auto-increment column, but can I simply add the AUTO_INCREMENT option to an existing column that is the primary key?
Changing the IDENTITY property is really a metadata only change. But to update the metadata directly requires starting the instance in single user mode and messing around with some columns in sys.syscolpars and is undocumented/unsupported and not something I would recommend or will give any additional details about.
For people coming across this answer on SQL Server 2012+ by far the easiest way of achieving this result of an auto incrementing column would be to create a SEQUENCE object and set the next value for seq as the column default.
Alternatively, or for previous versions (from 2005 onwards), the workaround posted on this connect item shows a completely supported way of doing this without any need for size of data operations using ALTER TABLE...SWITCH. Also blogged about on MSDN here. Though the code to achieve this is not very simple and there are restrictions - such as the table being changed can't be the target of a foreign key constraint.
Example code.
Set up test table with no identity column.
CREATE TABLE dbo.tblFoo
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2
Alter it to have an identity column (more or less instant).
BEGIN TRY;
BEGIN TRANSACTION;
/*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
set the correct seed in the table definition instead*/
DECLARE #TableScript nvarchar(max)
SELECT #TableScript =
'
CREATE TABLE dbo.Destination(
bar INT IDENTITY(' +
CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1) PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
'
FROM dbo.tblFoo
WITH (TABLOCKX,HOLDLOCK)
EXEC(#TableScript)
DROP TABLE dbo.tblFoo;
EXECUTE sp_rename N'dbo.Destination', N'tblFoo', 'OBJECT';
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
PRINT ERROR_MESSAGE();
END CATCH;
Test the result.
INSERT INTO dbo.tblFoo (filler,filler2)
OUTPUT inserted.*
VALUES ('foo','bar')
Gives
bar filler filler2
----------- --------- ---------
10001 foo bar
Clean up
DROP TABLE dbo.tblFoo
SQL Server: How to set auto-increment on a table with rows in it:
This strategy physically copies the rows around twice which can take a much longer time if the table you are copying is very large.
You could save out your data, drop and rebuild the table with the auto-increment and primary key, then load the data back in.
I'll walk you through with an example:
Step 1, create table foobar (without primary key or auto-increment):
CREATE TABLE foobar(
id int NOT NULL,
name nchar(100) NOT NULL,
)
Step 2, insert some rows
insert into foobar values(1, 'one');
insert into foobar values(2, 'two');
insert into foobar values(3, 'three');
Step 3, copy out foobar data into a temp table:
select * into temp_foobar from foobar
Step 4, drop table foobar:
drop table foobar;
Step 5, recreate your table with the primary key and auto-increment properties:
CREATE TABLE foobar(
id int primary key IDENTITY(1, 1) NOT NULL,
name nchar(100) NOT NULL,
)
Step 6, insert your data from temp table back into foobar
SET IDENTITY_INSERT temp_foobar ON
INSERT into foobar (id, name) select id, name from temp_foobar;
Step 7, drop your temp table, and check to see if it worked:
drop table temp_foobar;
select * from foobar;
You should get this, and when you inspect the foobar table, the id column is auto-increment of 1 and id is a primary key:
1 one
2 two
3 three
If you want to do this via the designer you can do it by following the instructions here "Save changes is not permitted" when changing an existing column to be nullable
Yes, you can. Go to Tools > Designers > Table and Designers and uncheck "Prevent Saving Changes That Prevent Table Recreation".
No, you can not add an auto increment option to an existing column with data, I think the option which you mentioned is the best.
Have a look here.
If you don't want to add a new column, and you can guarantee that your current int column is unique, you could select all of the data out into a temporary table, drop the table and recreate with the IDENTITY column specified. Then using SET IDENTITY INSERT ON you can insert all of your data in the temporary table into the new table.
Below script can be a good solution.Worked in large data as well.
ALTER DATABASE WMlive SET RECOVERY SIMPLE WITH NO_WAIT
ALTER TABLE WMBOMTABLE DROP CONSTRAINT PK_WMBomTable
ALTER TABLE WMBOMTABLE drop column BOMID
ALTER TABLE WMBOMTABLE ADD BomID int IDENTITY(1, 1) NOT NULL;
ALTER TABLE WMBOMTABLE ADD CONSTRAINT PK_WMBomTable PRIMARY KEY CLUSTERED (BomID);
ALTER DATABASE WMlive SET RECOVERY FULL WITH NO_WAIT

Resources