SQL: How to use a column that was just added - sql

I am trying to add 2 columns and then I would like to set some values to them but I get a compile-error saying the column does not exist. I am using the following script:
IF #LogProcessed = 0
Begin
IF NOT EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'SYSTM_FRM' and column_name = 'SF_Ip_TXT')
ALTER TABLE SYSTM_FRM add SF_Ip_TXT NVARCHAR(20)
IF NOT EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'SYSTM_FRM' and column_name = 'SF_Port_NUM')
ALTER TABLE SYSTM_FRM add SF_Port_NUM int
IF (EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'FRM' and column_name = 'FRM_Ip_TXT') AND
EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'FRM' and column_name = 'FRM_Ip_TXT'))
begin
Update dbo.SYSTM_FRM
SET dbo.SYSTM_FRM.SF_Ip_TXT = dbo.FRM.FRM_Ip_TXT,
dbo.SYSTM_FRM.SF_Port_NUM = dbo.FRM.FRM_Port_NUM
FROM dbo.FRM INNER JOIN dbo.SYSTM_FRM ON dbo.FRM.FRM_RCRD_NUM = dbo.SYSTM_FRM.SF_FrameRecord_NUM
ALTER TABLE FRM DROP COLUMN FRM_Ip_TXT
ALTER TABLE FRM DROP COLUMN FRM_Port_NUM
end
Update [Update_Log]
Set Update_Log_Processed = 1
Where [Update_Log_Version] = '00001'
end
Is there any way to use a column that I am adding in the same script?

you cannot save it in a proc like that
example
create table TestAdd2 (id int)
go
You cannot create this procedure
create proc prTest as
insert TestAdd2 values (1)
exec ('ALTER TABLE TestAdd2 add SF_Port_NUM int')
update TestAdd2 set id = 1,SF_Port_NUM = 2
select * from TestAdd2
GO
You get this error
Msg 207, Level 16, State 1, Procedure prTest, Line 7
Invalid column name 'SF_Port_NUM'.
This is because at parse time the column does not exist
However if you use dynamic SQL for the update you are good to go
create proc prTest2 as
insert TestAdd2 values (1)
exec ('ALTER TABLE TestAdd2 add SF_Port_NUM int')
exec ('update TestAdd2 set id = 1,SF_Port_NUM = 2')
select * from TestAdd2
GO
in your case your update statement would be
exec('Update dbo.SYSTM_FRM
SET dbo.SYSTM_FRM.SF_Ip_TXT = dbo.FRM.FRM_Ip_TXT,
dbo.SYSTM_FRM.SF_Port_NUM = dbo.FRM.FRM_Port_NUM
FROM dbo.FRM INNER JOIN dbo.SYSTM_FRM
ON dbo.FRM.FRM_RCRD_NUM = dbo.SYSTM_FRM.SF_FrameRecord_NUM')

Put a GO in between

All DDL statements should follow the statement seperator GO in order to make use of it

Related

There is already an object named '#BaseData' in the database

Below is a snippet of my code.
I am wanting to filter my data based upon a variable.
When I try to run the code, it returns an error of "There is already an object named '#BaseData' in the database.". I am not sure as to why this is the case; I have put extra checks within the IF statements to drop the temp table if it already exists but to no avail.
Are you able to help or provide an alternative solution please?
DECLARE #Variable AS VARCHAR(20) = 'Example1'
IF OBJECT_ID(N'TEMPDB..#BaseData') IS NOT NULL
DROP TABLE #BaseData
IF #Variable = 'Example1'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
END
IF #Variable = 'Example2'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
WHERE
[column] = 1
END
IF #Variable = 'Example3'
BEGIN
SELECT
*
INTO
#BaseData
FROM
[Database].[schema].[table]
WHERE
[column] = 0
END
While code is compiled by SQL, creation of same #table is found in each condition so it doesn't work.
One possible solution would be to create table and than insert data conditionally.
-- DROP TEMP TABLE IF EXISTS
IF OBJECT_ID(N'TEMPDB..#BaseData') IS NOT NULL
DROP TABLE #BaseData
GO
-- CRATE TEMP TABLE WITH TempId, AND SAME STRUCTURE AS YOUR TABLE
SELECT TOP 0 CONVERT(INT, 0)TempId, * INTO #BaseData FROM TestTable
-- DECLARE VARIABLE
DECLARE #Variable AS VARCHAR(20)= 'Example1'
-- INSERT DATA IN TABLE DEPENDING FROM CONDITION
IF (#Variable = 'Example1')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable
END
IF (#Variable = 'Example2')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable WHERE Id = 1
END
IF (#Variable = 'Example3')
BEGIN
INSERT INTO #BaseData SELECT * FROM TestTable WHERE Id = 2
END

Alter then update causes an error

I have simple script:
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.Columns
WHERE table_name = 'T1' AND column_name = 'C1')
BEGIN
ALTER Table T1
ADD C1 BIT NOT NULL CONSTRAINT DF_T1_C1 DEFAULT 0
UPDATE Table T1
SET C1 = 1
END
GO
I am getting error
Incorrect syntax near the keyword 'Table'.
I tried this solution but it didn't update column value. I came accross this but I think this is not my case as I don't want to catch exceptions or do any transaction. Do I have easy option to do this?
Putting GO seperator didn't help too.
As Joe Taras pointed out, I have changed my script but now getting error
Invalid column name 'C1'.
You need to ensure that that UPDATE isn't compiled until after you're actually created the column.
Put it in a separate context by using EXEC:
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.Columns
WHERE table_name = 'T1' AND column_name = 'C1')
BEGIN
ALTER Table T1
ADD C1 BIT NOT NULL CONSTRAINT DF_T1_C1 DEFAULT 0
EXEC('UPDATE Table T1
SET C1 = 1')
END
GO
Your row:
UPDATE Table T1 SET C1 = 1
has wrong because you have specified table keyword.
The correct syntax is:
UPDATE T1 SET C1 = 1
EDIT 1
Rewrite your script as follow, so after GO separator you'll update your field, so you are sure the DDL has taken by DBMS:
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.Columns
where table_name = 'T1' AND column_name = 'C1')
BEGIN
ALTER Table T1
ADD C1 BIT NOT NULL CONSTRAINT DF_T1_C1 DEFAULT 0
END
GO
UPDATE T1 SET C1 = 1
EDIT 2
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.Columns
where table_name = 'T1' AND column_name = 'C1')
BEGIN
ALTER Table T1
ADD C1 BIT NOT NULL CONSTRAINT DF_T1_C1 DEFAULT 0
EXEC('UPDATE T1 SET C1 = 1')
END
GO
if there is no entry in the table update cannot be done
try it after giving asingle entry it works

Not able to alter column after renaming it

I am first checking if column exist or not. If not then i rename existing column and then try to change its datatype. But when i run script i get error Invalid column name Age
if Not exists(select * from sys.columns
where Name = 'Age' and Object_ID = Object_ID('TestTable'))
begin
EXEC sp_RENAME 'TestTable.Name' , 'Age', 'COLUMN'
ALTER TABLE TestTable ALTER COLUMN Age int
Update TestTable set Age = 0
ALTER TABLE TestTable ALTER COLUMN Age int Not Null
end
What am i doing wrong here?
Try this. By splitting your If condition with Not Exists and exists.
if Not exists(select * from sys.columns
where Name = 'Age' and Object_ID = Object_ID('TestTable'))
BEGIN
EXEC sp_RENAME 'TestTable.Name' , 'Age', 'COLUMN'
END
GO
if exists(select * from sys.columns
where Name = 'Age' and Object_ID = Object_ID('TestTable'))
begin
ALTER TABLE TestTable ALTER COLUMN Age int
Update TestTable set Age = 0
ALTER TABLE TestTable ALTER COLUMN Age int Not Null
END
GO
Edit:
About Batch in SQL from here
A table cannot be changed and then the new columns referenced in the
same batch.
So, renaming and altering in the same batch not worked.
See here
When an error occurs while executing a batch of SQL statements,
No statements in the batch are executed.

SQL Server stored procedure/cursor

I have a list of 20 spatial tables (Zoom1-Zoom20) and from time invalid geometry pops up in these tables. When the invalid geometry occurs I run the following statement to find where the invalid geometry is:
SELECT ID FROM Zoom10 WhERE Location.STIsValid() = 0
Typically I have to run the above statement for every Zoom table (the error that leads to the invalid geometry does not indicate which zoom table has invalid geometry) and when a result is returned from the select statement I run the following statement to correct the geometry:
UPDATE MGeoZoom10 set Location = Location.MakeValid() where Location.STIsValid() = 0
My question is can this process be automated with a stored procedure that gets the list of zoom tables
select name from sys.tables where name like '%zoom'
and then loops through the zoom tables with
SELECT ID FROM Zoom10 WhERE Location.STIsValid() = 0
and if a result is returned it runs the update statement on the zoom table?
Try this:
sp_msforeachtable '
if ''?'' Like ''%Zoom%''
Begin
If Exists(SELECT ID FROM ? WhERE Location.STIsValid() = 0)
UPDATE ? set Location = Location.MakeValid() where Location.STIsValid() = 0
End
'
Do you have 2 UDFs called STIsValid and MakeValid? If so, you could do something like this...
SELECT id INTO #Processed FROM Sysobjects WHERE name = '(no such table)'
DECLARE #TableId int, #TableName varchar(255), #CorrectionSQL varchar(255)
SELECT #TableId = MIN(id) FROM Sysobjects WHERE type = 'U' AND name LIKE '%zoom'
AND id NOT IN (SELECT id FROM #Processed)
SET #TableId = ISNULL(#TableId, -1)
WHILE #TableId > -1 BEGIN
PRINT #TableId
SELECT #TableName = name FROM Sysobjects WHERE type = 'U' AND id = #TableId
SET #CorrectionSQL = 'UPDATE ' + #TableName + ' SET Location = dbo.MakeValid(Location) where dbo.STIsValid(Location) = 0'
PRINT #CorrectionSQL
EXEC(#CorrectionSQL)
INSERT INTO #Processed (id) VALUES(#TableId)
SELECT #TableId = MIN(id) FROM Sysobjects WHERE type = 'U' AND name IN ('DimAccount', 'DimCurrency', 'DimCustomer')
AND id NOT IN (SELECT id FROM #Processed)
END

How to add a new column AND insert rows conditionally (in the same script)

I want to add column to a table. If that part of my script executes, I also want to add some values to the table. How can I do it ?
if not exists (select 1 from sys.columns
where object_id = object_id('CAT_MASSUPDATETASKPARAM')
and name = 'ValueBoolean' )
begin
alter table CAT_MASSUPDATETASKPARAM add ValueBoolean bit NULL
end
go
IF (the first script was running do this script )
INSERT INTO CAT_MASSUPDATETASKPARAM ( ParentTaskIK,
ParamType,ParamName,ValueInt,ValueStr,ValueBoolean)
SELECT ParentTaskIK, 'Boolean','SHOW_CURRENT',NULL,NULL,1
FROM CAT_MASSUPDATETASKPARAM ,CAT_MASSUPDATETASK
WHERE CAT_MASSUPDATETASKPARAM.ParentTaskIK = CAT_MASSUPDATETASK.Id
AND CAT_MASSUPDATETASK.MassUpdateType in ('somthing','somthing1')
GROUP BY ParentTaskIK
go
You want the 2nd part to run only if the column was added in the first... Put it in the same begin-end block. But you need dynamic SQL because the column existence is checked at compile time.
if not exists (select 1 from sys.columns where object_id = object_id('CAT_MASSUPDATETASKPARAM') and name = 'ValueBoolean')
begin
alter table CAT_MASSUPDATETASKPARAM add ValueBoolean bit NULL;
EXEC ('
INSERT INTO CAT_MASSUPDATETASKPARAM ( ParentTaskIK, ParamType,ParamName,ValueInt,ValueStr,ValueBoolean)
select ParentTaskIK, ''Boolean'',''SHOW_CURRENT'',NULL,NULL,1
from CAT_MASSUPDATETASKPARAM ,CAT_MASSUPDATETASK
where CAT_MASSUPDATETASKPARAM.ParentTaskIK = CAT_MASSUPDATETASK.Id
and CAT_MASSUPDATETASK.MassUpdateType in (''somthing'',''somthing1'')
group by ParentTaskIK ');
end
go
Otherwise within the same session, you can use a temp table or some such marker:
if not exists (select 1 from sys.columns where object_id = object_id('CAT_MASSUPDATETASKPARAM') and name = 'ValueBoolean')
begin
alter table CAT_MASSUPDATETASKPARAM add ValueBoolean bit NULL;
create table #marker (id int);
end;
GO
if object_id('tempdb..#marker') is not null
INSERT INTO CAT_MASSUPDATETASKPARAM (
ParentTaskIK,ParamType,ParamName,ValueInt,ValueStr,ValueBoolean)
select ParentTaskIK, 'Boolean','SHOW_CURRENT',NULL,NULL,1
from CAT_MASSUPDATETASKPARAM ,CAT_MASSUPDATETASK
where CAT_MASSUPDATETASKPARAM.ParentTaskIK = CAT_MASSUPDATETASK.Id
and CAT_MASSUPDATETASK.MassUpdateType in ('somthing','somthing1')
group by ParentTaskIK;