SQL - Running multiple ALTER queries - sql

i'm having trouble with running multiple ALTER commands in a single query.
Whenever im trying to run the following code :
ALTER TABLE Book$
ALTER COLUMN PID INT NOT NULL
ALTER TABLE Book$
ADD CONSTRAINT pk_book PRIMARY KEY(PID)
I get an error :
Cannot define PRIMARY KEY constraint on nullable column in table 'Book$'.
But if i run the queries separately , first :
ALTER TABLE Book$
ALTER COLUMN PID INT NOT NULL
And then :
ALTER TABLE Book$
ADD CONSTRAINT pk_book PRIMARY KEY(PID)
Everything seems to work just fine.
What am i doing wrong? Thanks!

Add GO(batch separator) in between to fix the problem
ALTER TABLE Book$
ALTER COLUMN PID INT NOT NULL
GO
ALTER TABLE Book$
ADD CONSTRAINT pk_book PRIMARY KEY(PID)
Without GO the entire script will be considered as single script

I'm not sure which database you are using. To explain what is happening, though, you need to understand two phases of statement processing: Compilation and Execution.
The Compilation phase reads the statement and defines the execution plan. The Execution phase then runs the plan. Nothing about the table changes just because a statement is compiled.
What is happening is that the two statements are compiled and then executed. When the second is compiled, nothing has changed (well, except for the fact that the first statement's execution plan is stored somewhere). Hence, you are getting a compilation error.
When you run the two separately, the changes from the first take place and then the second does not generate an error.

Related

How to delete a mysql-enum-like column in sql server?

in orther to get a column similar to the mysql ENUM type, I wrote a sql query as follows
ALTER TABLE [DbName].[dbo].[MediaContent]
ADD MediaType nvarchar(50)
check(MediaType in ('audio','video','song','other'))
this worked as wished(for test): But now I want to delete this column without success. It seems like there no way to directly delete a column which has a constraint up on it.
How can I solve this issue? I want to delete this column and create another one.
here is the error message I get while the deletion
The object 'CK__MediaCont__Media__14270015' is dependent on column 'MediaType'.
ALTER TABLE DROP COLUMN MediaType failed
because one or more objects access this
column. (Microsoft SQL Server, Error: 5074)
The object referenced in the error message is the name of the constraint. You should be able to use the follow:
ALTER TABLE [DbName].[dbo].[MediaContent]
DROP CONSTRAINT CK__MediaCont__Media__14270015
You need to first drop the check constraint mentioned in the error message since that's stopping you from dropping the column. Following that you may drop the column.
Drop the constrain first then drop the column ,it will work

ADD and DROP SQL Server table constraint command in one transaction caused error

I have more SQL scripts (each for different version of the application) and I want to execute all scripts in one transaction.
I'm executing it from c# using:
ExecuteNonQuery(command, conn, trans)
on SqlCommand.
The SQL commands in the scripts are separated by GO separators. My C# code iterates through all scripts and creates collection of the SqlCommand based on the GO separator. The GO separator is excluded from SqlCommand execution. It is just a separator in script file.
All was working fine, but I have found one problem. I have in one script the following command:
ALTER TABLE [dbo].[RoleDataPermissions] WITH NOCHECK ADD CONSTRAINT
[FK_RoleDataPermissions_OrganizationUnits] FOREIGN KEY([OrganizationUnitID])
REFERENCES [OrganizationUnits] ([ID])
and in the another script (in another version of app this constraint was deleted) I have:
ALTER TABLE [dbo].[RoleDataPermissions]
DROP CONSTRAINT FK_RoleDataPermissions_OrganizationUnits
The first command passed fine, but the second one throws the exception:
'FK_RoleDataPermissions_OrganizationUnits' is not a constraint. Could not drop constraint. See previous errors.
I'm trying find out what is causing this problem. I think, that the problem is, that if all commands are executed under one transaction, so the first command is not committed and then the second one cannot find this constraint. I have tried also change the isolation level to readuncommited, but it doesn't help.
Do you have any idea how to deal with this?
thanks
Your analysis is not correct as a transaction can see it's own uncommitted data. This is easily demonstrated as below.
CREATE TABLE T1
(
ID INT PRIMARY KEY
)
CREATE TABLE T2
(
ID INT
)
BEGIN TRAN
ALTER TABLE T2
WITH NOCHECK ADD CONSTRAINT FK_Test FOREIGN KEY(ID) REFERENCES T1
GO
ALTER TABLE T2
DROP CONSTRAINT FK_Test
COMMIT
DROP TABLE T1, T2
The syntax you have posted is invalid however so quite likely the constraint isn't being created due to the syntax error and for some reason the exception isn't being reported in your application. Or (if your actual syntax is correct) maybe you are dropping the constraint twice.

Change primary key on SQL database

I have a database that I migrated from MySql using SQL Server Migration Assistant and it is now stored in Azure.
SSMA apparently generated a new primary key column, named ssma$rowid, for one of the tables. I am trying to change the PK back to Card_Key, but I am getting the following error:
An error was encountered while applying the changes.
An exception occurred while executing the Transact-SQL statement:
ALTER TABLE [carddb].[Cards] ALTER COLUMN [Card_Key] INT NOT NULL.
The index 'Card_Key' is dependent on column 'Card_Key'.
ALTER TABLE ALTER COLUMN Card_Key failed because one or more objects
access this column.
How can I make Card_Key the PK again?
The easiest might be to create a new table [cards2] with the correct primary key and copy your data from [cards] into the new table (just run a INSERT INTO cards2 ... SELECT ... FROM cards). Once that's done, you can drop (or rename to [cardsold] be on the safe side) the original table [cards], and rename the new table as [cards]: sp_rename cards2, cards
This should work.

check constraint in generated scripts

In SSMS, Tasks > Generate Scripts, I have selected a few tables and in the generated SQL I get:
ALTER TABLE [Project] WITH CHECK ADD CONSTRAINT [FK_Project_aspnet_Users] FOREIGN KEY([UserId])
REFERENCES [aspnet_Users] ([UserId])
GO
ALTER TABLE [Project] CHECK CONSTRAINT [FK_Project_aspnet_Users]
GO
Why does it CHECK in the second statement if WITH CHECK is specified in the first? The second statement appears directly after the first.
TIA
You are correct to observe that it is redundant.
It's just the way that SSMS generates scripts.
Note that the script could be modified after it is generated. That first statement could be changed to use 'WITH NO CHECK', and that second statement would not be redundant.
The purpose of the first statement is to add the constraint.
The purpose of the second statement is to enable the constraint.
At least, that's the way I read the script. If I were manually running the statements one by one, I might get a "constraint already exists" exception, but that constraint might not be enabled.
I would still run the second statement, to ensure the existing constraint gets enabled.

How to ALTER a table on iSeries that has constraints? Getting "*FILE in use." error

I have a table on a iSeries(IBM-i/AS400) which has some constraints. The table is created with SQL like so, with a handful of foreign keys linking from other tables to this table (actual SQL has been a bit obfuscated here):
CREATE TABLE ABCLIB.ABCDE (
DEIDN INTEGER NOT NULL WITH DEFAULT,
DETTL VARGRAPHIC (50) ALLOCATE(25),
DETYP CHAR (1) NOT NULL WITH DEFAULT);
ALTER TABLE ABCLIB.ABCDE ADD PRIMARY KEY (DEIDN);
ALTER TABLE ABCLIB.ABCFG ADD FOREIGN KEY (FGDEK)
REFERENCES ABCLIB.ABCDE (DEIDN)
ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE ABCLIB.ABCHI ADD FOREIGN KEY (HIDEK)
REFERENCES ABCLIB.ABCDE (DEIDN)
ON DELETE RESTRICT ON UPDATE RESTRICT;
Now, much later, I will need to alter that table to add a field:
ALTER TABLE ABCLIB.ABCDE ADD COLUMN DEICN VARGRAPHIC (100) ALLOCATE(50)
Which results in this message:
Row or object ABCDE in ABCLIB type *FILE in use.
I have checked and there are definitely no object locks on this table at this time. When I check the joblog, I see this:
Constraint cannot be removed from file Q_AT000000.
Constraint(s) not removed from file Q_AT000000.
File ABCDE in ABCLIB not changed.
Row or object ABCDE in ABCLIB type *FILE in use.
Now, I could of course remove and re-add the constraints in question, but I feel like this should not be necessary. The column I am adding has nothing to do with the constraints. I believe this probably is a result of the fact that in fact OS400 (i5/OS) is not really altering the existing table but instead is creating a new table and copying data in, and that is probably where the pain comes in.
But is there a way to possibly suspend the keys and then resume them after the alter?
(Answers that do not involve doing this with SQL or suggest creating the table differently in the first place are not helpful as they are not applicable here...)
The answer is: I missed the fact that there was a lock on one of the tables that had a foreign key pointing to that table. Or, put more bluntly: I am an idiot!
Does Enabling or disabling referential constraints help?