azure db drop pk and add a new one - sql

I have MS SQL database on Azure , and I want to drop my Primary key constraint and add another column as a primary key , every time I try to run the script to drop the primary key I get the error:
" Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again."
by running this script:
IF EXISTS (SELECT * FROM sys.key_constraints WHERE type = 'PK' AND parent_object_id = OBJECT_ID('dbo.Paypaltransaction') AND Name = 'PK_PaypalTransaction')
ALTER TABLE dbo.PaypalTransaction
DROP CONSTRAINT PK_PaypalTransaction
GO
Then I go and try to create another primary key :
-- add new primary key constraint on new column
ALTER TABLE dbo.PaypalTransaction
ADD CONSTRAINT PK_PaypalTransactionId
PRIMARY KEY CLUSTERED (PaypalTransactionId)
GO
and I get this error:
"Table 'PaypalTransaction' already has a primary key defined on it."
I understand the error's , but I can't delete the primary key because it appearently has to have one , and I can't add a new one because I already have one . Am I just stuck forever and ever and ever with the wrong column as my primary key :'(
I see This Question here that is the same and they ended up dropping the table and creating a new one - no way that is the only way to do this , that is just silly.

Copy over from the DBA.Se answer:
Q5) Can the primary key of a table be modified when is enforced via the clustered index if the table is populated?
A: No. Any operation that converts a populated clustered index into a heap will be blocked in SQL Azure, even if the table is empty:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key clustered (UserId, Id));
go
insert into Friend (UserId) values (1);
delete from Friend;
go
alter table Friend drop constraint pk_Friend;
As a side note: the constraint can be modified if the table is truncated.
The workaround to change the PK constraint of a populated table is to do the good old sp_rename trick:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key clustered (UserId, Id));
go
insert into Friend (UserId) values (1);
go
create table FriendNew (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend_New primary key clustered (Id, UserId));
go
set identity_insert FriendNew on;
insert into FriendNew (UserId, Id)
select UserId, Id
from Friend;
set identity_insert FriendNew off;
go
begin transaction
exec sp_rename 'Friend', 'FriendOld';
exec sp_rename 'FriendNew', 'Friend';
commit;
go
sp_help 'Friend';
The sp_rename approach has some issues, most importantly being that permissions on the table do not carry over during the rename, as well as foreign key constraints.

I have just tested and it seems that on SQL AZURE V12 it is possible!

Related

Database contains foreign key that doesn exist even though there is a foreign key constraint?

I am working with a database where there is a foreign key ID that doesn't exist even though there is a foreign key constraint.
There is a table called "Workplace" with a foreign key column called "AddressID" pointing to another table called "Address"
The foreign key is as follows:
ALTER TABLE [dbo].[Workplace] WITH NOCHECK ADD CONSTRAINT [FK_Workplace_Address] FOREIGN KEY([AddressID])
REFERENCES [dbo].[Address] ([ID])
GO
ALTER TABLE [dbo].[Workplace] CHECK CONSTRAINT [FK_Workplace_Address]
GO
For one particular row in the Workplace table, the AddressID has a value of "1".
When I run select * from Address where ID = 1 there is no result.
Then I ran update Workplace set AddressID = 3 where Workplace.ID = 20 the value changed to 3 and I have verified that an Address with ID 3 exists.
Then I ran update Workplace set AddressID = 1 where Workplace.ID = 20 again and I get the error
The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database db_name, table "dbo.Address", column 'ID'.
I don't understand how the value 1 could have been put there in the first place. The Address with ID=1 couldn't have been deleted after the constraint was put in place. The constraint creation would also fail if the record was deleted in the first place. Does anyone know how this could be possible?
This is a database on Windows Server 2016, SQL Server 12.0.4237.0
You create your FOREIGN KEY with NOCHECK, as a result the values that already exist in the table are not checked. This can be replicated with the following:
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int)
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO
ALTER TABLE dbo.WorkPlace WITH NOCHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID);
GO
ALTER TABLE dbo.Workplace CHECK CONSTRAINT FK_Workplace_Address;
GO
INSERT INTO dbo.Workplace
VALUES(2,3); --Fails
GO
UPDATE dbo.Workplace
SET AddressID = 2
WHERE ID = 1; --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;
As you can see, only rows that are INSERTed or UPDATEd after the constraint was created (with NOCHECK) are validated; the first row INSERTed is left as it was, with a reference to a row that does not exist.
Instead, create the key without NOCHECK defined, or with CHECK, and the statement will fail when you try to create it:
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int)
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO
ALTER TABLE dbo.WorkPlace WITH CHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID); --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;
This generates the error below:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database "Sandbox", table "dbo.Address", column 'ID'.
Alternatively, create the key when you create the tables; though it's likely too late for that now.
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int CONSTRAINT FK_Workplace_Address FOREIGN KEY REFERENCES dbo.Address(ID));
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;

SQL The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Score_Gebruikersnaam"

I have a create script for my SQL database (see below). Everything works fine except when I run the INSERT INTO Scores() I get an error.
The error I get is:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Score_Gebruikersnaam". The conflict occurred in database "gamescores", table "dbo.Players", column 'gebruikersnaam'
I don't understand what I'm doing wrong so please help me :)
I already tried to drop the database first and then run the rest of the script but that didn't help. I think something went wrong with the foreign key...
Thanks!
USE master;
GO
DROP DATABASE IF EXISTS [gamescores];
CREATE DATABASE gamescores;
GO
USE gamescores;
GO
SET DATEFORMAT dmy;
CREATE TABLE [Players]
(
[gebruikersnaam] VARCHAR(75) NOT NULL,
[voornaam] VARCHAR(75) NOT NULL,
[achternaam] VARCHAR(75) NOT NULL,
[emailadres] VARCHAR(75) NOT NULL,
[geboortdatum] DATE NOT NULL
);
CREATE TABLE [Scores]
(
[scoreID] INT IDENTITY(1,1) NOT NULL,
[gebruikersnaam] VARCHAR(75) NOT NULL,
[aantalScore] INT NOT NULL,
[datum] DATE NOT NULL
);
ALTER TABLE [Players]
ADD CONSTRAINT [PK_Speler]
PRIMARY KEY (gebruikersnaam);
ALTER TABLE [Scores]
ADD CONSTRAINT [PK_Score]
PRIMARY KEY (scoreID);
ALTER TABLE [Players]
ADD CONSTRAINT [AK_Speler_Emailadres]
UNIQUE (emailadres)
ALTER TABLE [Scores]
ADD CONSTRAINT [FK_Score_Gebruikersnaam]
FOREIGN KEY (gebruikersnaam) REFERENCES Players(gebruikersnaam);
GO
INSERT INTO Players([gebruikersnaam], [voornaam], [achternaam], [emailadres], [geboortdatum])
VALUES ('apraundlin1', 'Angelle', 'Praundlin', 'apraundlin1#mapy.cz', '15-9-1997'),
('rnoore3', 'Rebekah', 'Noore', 'rnoore3#vk.com', '9-10-1987'),
('nplevinh', 'Nicolais', 'Plevin', 'nplevinh#mediafire.com', '18-3-2001');
-- SCORE table vullen
INSERT INTO Scores([gebruikersnaam], [aantalScore], [datum])
VALUES ('rsprasen0', 551, '15-5-2021'),
('fwhawell8', 309, '8-4-2021'),
('rgravett9', 1063, '16-11-2021');
You got an error because the database schema, though a foreign key, enforces that a player referenced in the scores table must first exist in the players table. Add the player to the players table, before trying to update their score in the scores table.

Alter datatype of clustered index primary key in table

I have a table with
CONSTRAINT [user_const] PRIMARY KEY CLUSTERED ([id] ASC, [group] ASC)
I want to change the datatype of group to NVARCHAR from NCHAR.
Simply running
ALTER TABLE [dbo].[user] ALTER COLUMN [group] NVARCHAR (50) NOT NULL;
gives me an error:
The object 'user_const' is dependent on column 'group'.
CHECK NOCHECK does not work as
This action applies only to foreign key and check constraints.
So, I thought I should drop the constraint and recreate it
ALTER TABLE [dbo].[user] DROP CONSTRAINT [user_const];
ALTER TABLE [dbo].[user] ALTER COLUMN [group] NVARCHAR (50) NOT NULL;
ALTER TABLE [dbo].[user] ADD CONSTRAINT CONSTRAINT [user_const] PRIMARY KEY CLUSTERED ([id] ASC, [group] ASC)
But error reads
Tables without a clustered index are not supported in this version of SQL Server.
How can I alter the datatype of a column which is a primary key constraint?
Azure does not support tables without clustered indexes. Read here
http://msdn.microsoft.com/library/azure/ee336245.aspx#cir
In order to change the data type, you are going to have to create a second table with the new datatypes, move the data over, and then rename.
Since you're changing the primary key, you're effectively rebuilding the entire table anyway, so you might as well build a new table with the new format and rename to get the name right. I haven't run this so it might need a little tweaking, but something like this:
-- check to see if we've already run this script and swap table names and just run it again with the old data if we have
IF EXISTS (SELECT * FROM SysObjects WHERE name='MyTable_bak' AND type='U')
IF EXISTS (SELECT * FROM SysObjects WHERE name='MyTable' AND type='U')
DROP TABLE MyTable
ELSE
EXEC sp_rename 'MyTable', 'MyTable_bak'
GO
-- create the new table with updated columns
CREATE TABLE MyTable (
[id] BIGINT NOT NULL,
[group] NVARCHAR(50) NOT NULL,
CONSTRAINT PK_MyTable PRIMARY KEY CLUSTERED
(
[id] ASC, [group] ASC
))
GO
-- copy in the data from the old version
INSERT MyTable([id],[group])
SELECT [id],[group]
FROM MyTable_bak
GO
-- drop the old table (maybe wait to do this until testing is complete?)
DROP TABLE MyTable_bak

Alter Table Add Column with Default value And FK, that Value no existing in FK Reference Data

This is My Tables :
Member : Id, ....
Product: Id, ....
My Member Table have some values none if them with Id = 0 and I don't want to add any member with Id = 0, So I try to run this Script:
ALTER TABLE [Product]
ADD [Member_Id] BIGINT NOT NULL DEFAULT(0),
CONSTRAINT [FK_Product_Member] FOREIGN KEY ([Member_Id]) REFERENCES [Member];
So There is an Error :
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Product_Member".
So I try this one:
SET IDENTITY_INSERT [Member] ON
INSERT INTO [Member] ([Id]) VALUES (0);
SET IDENTITY_INSERT [Member] OFF
ALTER TABLE [Product]
ADD [Member_Id] BIGINT NOT NULL DEFAULT(0),
CONSTRAINT [FK_Product_Member] FOREIGN KEY ([Member_Id]) REFERENCES [Member];
DELETE FROM [Member] WHERE [Member].[Id] = 0;
Then The new Error is:
The DELETE statement conflicted with the REFERENCE constraint "FK_Product_Member".
If I try to create all Tables again, every thing will be OK of course with lost my Data so need to get backup, create tables and restore data. So Is there any way to alter Table with this situation? what is your suggestion?
The only "value" that you can have in a referencing table, such that the foreign key constraint is not enforced, is NULL. Not 0, or any other magic value.
So the obvious solution is to allow NULLs:
ALTER TABLE [Product]
ADD [Member_Id] BIGINT NULL,
CONSTRAINT [FK_Product_Member] FOREIGN KEY ([Member_Id]) REFERENCES [Member];
your "alter table" is the better way to do this.but at first you are adding the table with value "0" and this is "FOREIGN KEY" but you have not a Member with value "0" so you get error.
the best way as a know is .alter table and then make the true value to the new column and then alter the column and set that to the "FOREIGN KEY"

How to create composite primary key in SQL Server 2008

I want to create tables in SQL Server 2008, but I don't know how to create composite primary key. How can I achieve this?
create table my_table (
column_a integer not null,
column_b integer not null,
column_c varchar(50),
primary key (column_a, column_b)
);
CREATE TABLE UserGroup
(
[User_Id] INT NOT NULL,
[Group_Id] INT NOT NULL
CONSTRAINT PK_UserGroup PRIMARY KEY NONCLUSTERED ([User_Id], [Group_Id])
)
Via Enterprise Manager (SSMS)...
Right Click on the Table you wish to create the composite key on and select Design.
Highlight the columns you wish to form as a composite key
Right Click over those columns and Set Primary Key
To see the SQL you can then right click on the Table > Script Table As > Create To
I know I'm late to this party, but for an existing table, try:
ALTER table TABLE_NAME
ADD CONSTRAINT [name of your PK, e.g. PK_TableName] PRIMARY KEY CLUSTERED (column1, column2, etc.)
For MSSQL Server 2012
CREATE TABLE usrgroup(
usr_id int FOREIGN KEY REFERENCES users(id),
grp_id int FOREIGN KEY REFERENCES groups(id),
PRIMARY KEY (usr_id, grp_id)
)
UPDATE
I should add !
If you want to add foreign / primary keys altering, firstly you should create the keys with constraints or you can not make changes. Like this below:
CREATE TABLE usrgroup(
usr_id int,
grp_id int,
CONSTRAINT FK_usrgroup_usrid FOREIGN KEY (usr_id) REFERENCES users(id),
CONSTRAINT FK_usrgroup_groupid FOREIGN KEY (grp_id) REFERENCES groups(id),
CONSTRAINT PK_usrgroup PRIMARY KEY (usr_id,grp_id)
)
Actually last way is healthier and serial. You can look the FK/PK Constraint names (dbo.dbname > Keys > ..) but if you do not use a constraint, MSSQL auto-creates random FK/PK names. You will need to look at every change (alter table) you need.
I recommend that you set a standard for yourself; the constraint should be defined according to the your standard. You will not have to memorize and you will not have to think too long. In short, you work faster.
First create the database and table, manually adding the columns. In which column to be primary key. You should right click this column and set primary key and set the seed value of the primary key.
To create a composite unique key on table
ALTER TABLE [TableName] ADD UNIQUE ([Column1], [Column2], [column3]);
CREATE TABLE UserGroup
(
[User_Id] INT Foreign Key,
[Group_Id] INT foreign key,
PRIMARY KEY ([User_Id], [Group_Id])
)