SQL - Continue running all SQL statements even after error - sql

I have some queries like this
Alter Table Table1 ALTER COLUMN T1 varchar(MAX);
Alter Table Table1 ALTER COLUMN T2 varchar(MAX);
Alter Table Table1 ALTER COLUMN T3 varchar(MAX);
--Table2 does not have a column "R1" and is likely to give error
Alter Table Table2 ALTER COLUMN R1 varchar(MAX);
Alter Table Table2 ALTER COLUMN T1 varchar(MAX);
Alter Table Table2 ALTER COLUMN T2 varchar(MAX);
Alter Table Table2 ALTER COLUMN T3 varchar(MAX);
Possible Error
Now in the 4th statement it is likely that a message would pop because there is no field in Table2 named R1.
Need
I need a way so that all the statement gets executed even after receiving the error.
My Approach
I tried to execute these statements individually to receive error message for every line but it takes too much time as it makes 7 times connection to a server which is connected to the PC by internet . So, i used all those query together to get records in one connection but it breaks the command on 4th line as the statement is invalid.
Any suggestion or piece of code is appreciated

You should use 'GO' between instructions in order to contine the execution no matter on the errors:
Alter Table Table1 ALTER COLUMN T1 varchar(MAX);
GO
Alter Table Table1 ALTER COLUMN T2 varchar(MAX);
GO
Alter Table Table1 ALTER COLUMN T3 varchar(MAX);
GO
Alter Table Table2 ALTER COLUMN R1 varchar(MAX);
GO
Alter Table Table2 ALTER COLUMN T1 varchar(MAX);
GO
Alter Table Table2 ALTER COLUMN T2 varchar(MAX);
GO
Alter Table Table2 ALTER COLUMN T3 varchar(MAX);
GO
This will give you all messages and will execute all the sentences one after each other. Those are my logs on a similar situation. As you will see, various errors are notified, and not only one:
NOTE: The catch behavior depends on the severity of the error, this
link from the MSDOC explains how try_catch works
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql?view=sql-server-2017
Hope it helps :)

Use a try-catch block:
Alter Table Table1 ALTER COLUMN T1 varchar(MAX);
Alter Table Table1 ALTER COLUMN T2 varchar(MAX);
Alter Table Table1 ALTER COLUMN T3 varchar(MAX);
BEGIN TRY
Alter Table Table2 ALTER COLUMN R1 varchar(MAX);
END TRY
BEGIN CATCH
print 'error altering column R1 of Table2';
END CATCH;
Alter Table Table2 ALTER COLUMN T1 varchar(MAX);
Alter Table Table2 ALTER COLUMN T2 varchar(MAX);
Alter Table Table2 ALTER COLUMN T3 varchar(MAX);

If Table2 does not have column R1 then the statement 'Alter Table Table2 ALTER COLUMN R1 varchar(MAX);' will not be a valid sql statement so the statement will not try to run so the catch will not happen. If instead you execute the statement it will try to run and the catch will work.
Alter Table Table1 ALTER COLUMN T1 varchar(MAX);
Alter Table Table1 ALTER COLUMN T2 varchar(MAX);
Alter Table Table1 ALTER COLUMN T3 varchar(MAX);
BEGIN TRY
execute ('Alter Table Table2 ALTER COLUMN R1 varchar(MAX);')
END TRY
BEGIN CATCH
print 'error altering column R1 of Table2';
END CATCH;
Alter Table Table2 ALTER COLUMN T1 varchar(MAX);
Alter Table Table2 ALTER COLUMN T2 varchar(MAX);
Alter Table Table2 ALTER COLUMN T3 varchar(MAX);

I have noticed that we get the desired behavior if the commands are run from inside an open session.
mysql -u root -p myDB < commands.sql >> stops on the first error
mysql -u root -p myDB
(after login)
source commands.sql
^^^ continues even after errors occur

Related

execute constraint on update sql

I have a constraint that return datetime for a column (date).
On insert work it! Now I would like update column date with new value of getdate() when an update statement execute. Any idea?
My constraint:
ALTER TABLE [tablename] ADD CONSTRAINT [constraintName]
DEFAULT (getdate()) FOR [column]
MY DBMS is Microsoft SQL Server 2012
You can do it using a trigger like this:
CREATE TRIGGER updTableDate
ON [Table]
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE [Table] SET modified = GETDATE() WHERE [primary_key] IN (SELECT [primary_key] FROM INSERTED)
END
Or better:
CREATE TRIGGER updTableDate
ON [Table]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE [Table] t SET modified = GetDate() FROM INSERTED AS i WHERE t.id = i.id
END

SQL: multiple statements within a BEGIN and END

I'm trying to add a new column to an existing table which will be populated by a unique Guid value. I'm trying the following code:
IF NOT EXISTS(select * from sys.columns
where Name = N'Product_GUID' and Object_ID = Object_ID(N'dbo.Product'))
BEGIN
PRINT 'Creating new GUID column in dbo.Product table'
ALTER TABLE dbo.Product
ADD Product_GUID uniqueidentifier NULL
UPDATE dbo.Product
SET Product_Guid=NEWID()
ALTER TABLE dbo.Product
ALTER COLUMN Product_Guid uniqueidentifier NOT NULL
END
This won't work becasue the second statement doesn't recognise the new column name. I can't put GO or ; at the end of each statement though, presumably because I'm in the middle of the BEGIN/END block.
What's the best way of solving this dilemma?
The statement doing the update must be compiled after the column is added.
The way this is usually done is wrapping the statements in an EXEC:
EXEC(' UPDATE dbo.Product
SET Product_Guid = NEWID()
ALTER TABLE dbo.Product
ALTER COLUMN Product_Guid uniqueidentifier NOT NULL
')
It seems like you want to set the default value and have the column be not null. You'll get the same effect if you just set the default value to NEWID()
IF NOT EXISTS(select * from sys.columns
where Name = N'Product_GUID' and Object_ID = Object_ID(N'dbo.Product'))
BEGIN
PRINT 'Creating new GUID column in dbo.Product table'
ALTER TABLE dbo.Product
ADD Product_GUID uniqueidentifier NOT NULL DEFAULT NEWID()
END
If you need to remove the constraint after, you can create the DEFAULT constraint after you define the column in the alter statement and then drop the named constraint right after. If you don't name the constraint you'll have to get the name from sys.objects and then do dynamic sql to remove it.
IF NOT EXISTS(select * from sys.columns
where Name = N'Product_GUID' and Object_ID = Object_ID(N'dbo.Product'))
BEGIN
PRINT 'Creating new GUID column in dbo.Product table'
ALTER TABLE dbo.Product
ADD Product_GUID uniqueidentifier NOT NULL,
CONSTRAINT Default_Product_GUID DEFAULT NEWID() FOR Product_GUID;
ALTER TABLE dbo.Product DROP CONSTRAINT Default_Product_GUID
END
You could just update the table afterwards and then alter it in another code block, a little something like this:
IF NOT EXISTS(select * from sys.columns
where Name = N'Product_GUID' and Object_ID = Object_ID(N'dbo.Product'))
BEGIN
PRINT 'Creating new GUID column in dbo.Product table'
ALTER TABLE dbo.Product
ADD Product_GUID uniqueidentifier NULL
END
GO
UPDATE dbo.Product
SET Product_Guid=NEWID()
Where Product_Guid is null
if ##ROWCOUNT <> 0
Begin
ALTER TABLE dbo.Product
ALTER COLUMN Product_Guid uniqueidentifier NOT NULL
End

sql server 2008 update table

I have stored procedure that insert data to table
on this procedure after inserting data to the table i want to update data in this table by execute another procedure
but the data not updated.
just when i exec the updateTable procedure after the first procedure it works, but i need to exec the updateTable procedure from the first procedure!!!
this is the first procedure:
CREATE PROCEDURE a
AS
BEGIN
insert into tbl
select * from tempTable
exec updateTable
end
the procedure that update the table look like this:
ALTER procedure [dbo].[updateTable]
AS
BEGIN
update tbl
set tbl.name= users.name
from dbo.tbl tbl
inner join
dbo.users users
on users.id=tbl.id
END
what can i do????

Why does SQL Server keep creating a DF constraint?

I'm trying to create upgrade and backout scripts in SQL. The upgrade script adds a column like so:
IF NOT EXISTS (SELECT * FROM sys.columns WHERE Name = N'ColumnName'
AND object_id = OBJECT_ID(N'[dbo].[TableName]'))
ALTER TABLE TableName
ADD ColumnName bit NOT NULL DEFAULT(0)
The backout script removes the column like so:
IF EXISTS (SELECT * FROM sys.columns WHERE Name = N'ColumnName'
AND object_id = OBJECT_ID(N'[dbo].[TableName]'))
ALTER TABLE TableName
DROP COLUMN ColumnName
However, the backout script throws this error:
Msg 5074, Level 16, State 1, Line 5
The object 'DF__TableName__ColumnName__1BF3D5BD' is dependent on column 'ColumnName'.
Msg 4922, Level 16, State 9, Line 5
ALTER TABLE DROP COLUMN ColumnName failed because one or more objects access this column.
I know how to drop the constraint, but the constraint's name changes everytime (the suffix changes). I either need SQL Server to stop creating this randomly-named constraint OR I need to be able to remove the constraint in my script using wild-card characters, since the name changes.
This is the default constraint that is added because of the DEFAULT(0) in your newly added column.
You can name this yourself so it has a known fixed name rather than relying on the auto name generation.
ALTER TABLE TableName
ADD ColumnName bit NOT NULL CONSTRAINT DF_Some_Fixed_Name DEFAULT(0)
Then to remove the column and constraint together
ALTER TABLE dbo.TableName
DROP CONSTRAINT DF_Some_Fixed_Name, COLUMN ColumnName
Run this:
declare #name as nvarchar(255);
SELECT #name = name FROM dbo.sysobjects
WHERE name LIKE 'DF__XXX__YYY__%' and type = 'D'
IF #name IS NOT NULL BEGIN
EXEC('ALTER TABLE XXX DROP CONSTRAINT ' + #name);
END
Run this if you want remove constraint:
DECLARE #tableName NVARCHAR(255) = '[INSERT]';
DECLARE #first5CharsFromColumnName NVARCHAR(255) = '[INSERT]';
DECLARE #name NVARCHAR(255);
SELECT #name = d.name FROM dbo.sysobjects d
INNER JOIN dbo.sysobjects t ON t.id = d.parent_obj
WHERE d.name LIKE '%'+#first5CharsFromColumnName+'%' AND d.type = 'D' AND t.name = #tableName
IF #name IS NOT NULL BEGIN
EXEC('ALTER TABLE '+#tableName+' DROP CONSTRAINT ' + #name);
END

Inserting duplicate record in Master-Detail Tables using Stored Procedure

I have the following Database Structure
Table1
============
T1ID
Fld1
Table2
============
T2ID
T1ID(Foreign Key from Table1)
Fld1
Table3
============
T3ID
T2ID(Foreign Key from Table2)
Fld1
Now first I will filter Table2 and Table3 data based on T1ID.
After that I am required to duplicate these filtered record in the same tables. I want to accomplish this using stored procedure. I have seen examples in which data is duplicated in one table but I don't have idea how to achieve this in these two master detail tables.
declare #T1ID int = 1
declare #T table(OldT2ID int, NewT2ID int)
merge Table2 as T
using (select T2ID, Fld1
from Table2
where T1ID = #T1ID) as S
on (0 = 1)
when not matched then
insert (T1ID, Fld1) values (#T1ID, S.Fld1)
output S.T2ID, inserted.T2ID into #T;
insert into Table3(T2ID, Fld1)
select T.NewT2ID, T3.Fld1
from Table3 as T3
inner join #T as T
on T3.T2ID = T.OldT2ID
I'm assuming that T1ID, T2ID, T3ID are identities with positive increment. I'm using two tricks:
1) when inserting new values into a table to distinguish old values from new, I'm using the value of the identity column. If it's more then the last seen maximum, then it's a newly inserted value. However for this to stay true we need to make sure that no other values was added to the table, thus I'm setting the isolation level of transaction to serializable.
2) I'm creating a temporary column in table2 so that I can keep track of old t2id against newly inserted ones. I drop the column at the end of the operation.
And now the code:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DoIt]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[DoIt]
GO
CREATE PROCEDURE [dbo].[DoIt]
#T1ID int
AS
BEGIN
declare #T1IDString nvarchar(10) = cast(#T1ID as nvarchar(10))
declare #sql nvarchar(255)
declare #Table2max nvarchar(10)
set transaction isolation level serializable
begin transaction
select #Table2max = cast(max(T2ID) as nvarchar(10)) from Table2
exec dbo.sp_executesql #statement = N'alter table Table2 add [oldT2ID] [int] null'
set #sql = N'insert into Table2 (T1ID,fld1,oldT2ID) select T1ID,fld1,T2ID from Table2 where T1ID = ' + #T1IDString
EXEC dbo.sp_executesql #statement = #sql
set #sql = N'insert into Table3 select t2.T2ID, t3.fld1 from Table3 t3 join Table2 t2 on t3.T2ID = t2.oldT2ID where t2.T1ID = '
+ #T1IDString + ' and t2.T2ID > ' + #Table2max
exec dbo.sp_executesql #statement = #sql
exec dbo.sp_executesql #statement = N'alter table Table2 drop column [oldT2ID]'
commit transaction
END
GO