T-SQL IF statement explanation - sql

I'm really puzzled by this one!! I'm sure it's simple but really can't figure it out!!
DECLARE #jobid INT = 100
IF (#JobID >= 0)
BEGIN
SELECT * into #tmp FROM Persons
end
ELSE
BEGIN
SELECT * into #tmp FROM Persons1
end
It gives an error that the #tmp table already exists! Why it would validate both statements !
Of course my original query is huge and doing more, but that's a sample to illustrate my error.
Can anybody explain it please?
The #tmp table is not there, even when you try to drop it or change the name, still the engine validates both statements!
I'm using 2008 R2.
Thanks
Jason

You run it over Linked Server? Or you not deleted the one from previous run.
Try to create #tmp table prior to IF statement:
CREATE TABLE #tmp(fields...)
DECLARE #jobid INT = 100
IF (#JobID >= 0)
BEGIN
INSERT #tmp
SELECT * FROM Persons
end
ELSE
BEGIN
INSERT #Tmp
SELECT * FROM Persons1
end
or delete provious one
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
EXEC('DROP TABLE #tmp')
GO
DECLARE #jobid INT = 100
IF (#JobID >= 0)
BEGIN
SELECT * into #tmp FROM Persons
end
ELSE
BEGIN
SELECT * into #tmp FROM Persons1
end

#tmp may already be created in tempDB from previous runs of your query. If you are not using #tmp anywhere in your query prior to that block, you could do something like the following prior to that block of code to ensure it's always ready to go:
IF OBJECT_ID('tempDB..#tmp') IS NOT NULL
DROP TABLE #tmp

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

Switch case with storing results into same table in SQL

I want to store the results into table with same name as per the condition. How to achieve the same ? Following is the code:
While executing it throws error that #a already exists.
IF #Input ='1'
BEGIN
drop #a
SELECT *
INTO #a
FROM table1
END;
ELSE IF #Input ='2'
BEGIN
drop #a
SELECT *
INTO #a
FROM table2
END;
You can use this solution using a global temporary table (maybe not the best / safest solution). The statements get executed with EXECUTE:
DECLARE #Input VARCHAR(20) = '1'
IF OBJECT_ID('tempdb..##a') IS NOT NULL
BEGIN
DROP TABLE ##a
END
IF #Input = '1'
EXEC ('SELECT * INTO ##a FROM table1;')
ELSE IF #Input = '2'
EXEC ('SELECT * INTO ##a FROM table2;')
-- you can implement steps here to create a local temporary table.
-- see: https://stackoverflow.com/questions/9534990/tsql-select-into-temp-table-from-dynamic-sql
SELECT * FROM ##a
Also have a look at this question: TSQL select into Temp table from dynamic sql. There is also described how you can get the data as local temporary table in two different ways (using a global temporary table or a view).
The problem using the EXECUTE function is leaving the scope.
try this
if object_id('tempdb..#a') is not null
drop table #a
IF #Input ='1'
BEGIN
SELECT *
INTO #a
FROM table1
END;
ELSE IF #Input ='2'
BEGIN
SELECT *
INTO #a
FROM table2
END;

how to insert cases into a table based on a parameter without duplicating the main select query?

I have a insert statement in sql server 2008 like below:
INSERT INTO MYTABLE
SELECT Id,Name,Date
FROM #temp
...joins...
where ...conditions...
I need to add a parameter to the code, and based on the parameter I will decide which table the output data should be inserted into. Check below:
declare #checkValue bit;
if (#checkValue = 1)
begin
INSERT INTO MYTABLE
SELECT Id,Name,Date
FROM #temp
...joins...
where ...conditions...
end
else
begin
INSERT INTO MY_OTHER_TABLE
SELECT Id,Name,Date
FROM #temp
...joins...
where ...conditions...
end
I handled the situation like above for now, however the main query is pretty long and I do not want to duplicate it, it does not look professional to me. I am looking for a better way to deal with such an issue. Any help or advice should be appreciated. Thanks.
You could use dynamic SQL (evil :), like so:
declare #cmd varchar(max) = '
INSERT INTO ' + #tableName + '
SELECT ...
';
execute (#cmd);
Or you create stored procedures (one statically INSERTs to table A, another one into table B >> code duplication) which are called depending on #checkValue, or a combination of both like here:
Stored procedure to insert values into dynamic table
create SP:
CREATE PROCEDURE ExampleSelect
AS
SELECT Id,Name,Date
FROM #temp
...joins...
where ...conditions...
GO
use insert..exec to insert data:
declare #checkValue bit;
if (#checkValue = 1)
begin
INSERT INTO MYTABLE
EXEC ExampleSelect
end
else
begin
INSERT INTO MY_OTHER_TABLE
EXEC ExampleSelect
end

How to write nested if statements in SQL Server 2008

I have a query in SQL Server 2008 like below:
declare #checkValue int = 1
IF (#checkValue = 1)
(
IF OBJECT_ID('tempdb..#newtable') IS NOT NULL DROP TABLE #newtable
Select Id
into #newtable
From #oldtable
);
This is not working since the second if clause which is inside the main IF clause. How can I fix it and use nested if statements like that?
Any help would be appreciated. Thanks
Almost, but you need BEGIN and END instead of parenthesis:
declare #checkValue int = 1
IF (#checkValue = 1)
BEGIN
IF OBJECT_ID('tempdb..#newtable') IS NOT NULL DROP TABLE #newtable
Select Id
into #newtable
From #oldtable
END;

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

I am trying the following query
if exists (select 1 from emp where eid = 6)
begin
if object_id('tempdb..#columntable') is not null
begin
drop table #columntable
end
create table #columntable (oldcolumns varchar(100))
end
else
begin
if object_id('tempdb..#columntable') is not null
begin
drop table #columntable
end
create table #columntable (newcolumns varchar(100))
end
But I am getting the error
Msg 2714, Level 16, State 1, Line 8
There is already an object named '#columntable' in the database.
Can anyone suggest why? The same query works fine if I do not write the else part.
This is a SQL Server parser error unfortunately (confirmed by Microsoft).
#DizGrizz is also right - SELECT .. INTO #SomeTable doesn't work if repeated in IF .. ELSE statements.
IF .. ELSE .. CREATE TABLE #SomeTempTable
In answer to the actual question, creating then altering the table works (you also only have to check and drop once)...
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
BEGIN
DROP TABLE #MyTempTable
END
CREATE TABLE #MyTempTable (DummyColumn BIT)
IF EXISTS (SELECT 1 FROM EMP WHERE EID = 6)
BEGIN
ALTER TABLE #MyTempTable
ADD MyColumnType1 VARCHAR(100)
ALTER TABLE #MyTempTable
DROP COLUMN DummyColumn
END
ELSE
BEGIN
ALTER TABLE #MyTempTable
ADD MyColumnType2 VARCHAR(100)
ALTER TABLE #MyTempTable
DROP COLUMN DummyColumn
END
IF .. ELSE .. SELECT INTO #SomeTempTable
The issue I had however was the same as #DizGrizz: IF .. ELSE combined with SELECT .. INTO #SomeTable fails. As a workaround it's possible to select the top 0 rows (i.e. none) to create the table with the correct column types. (This insulates the script from column type changes and also avoids the pain of declaring every type.) INSERT INTO can then be used, provided IDENTITY_INSERT is set to ON to prevent errors:
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
DROP TABLE #MyTempTable
-- This creates the table, but avoids having to declare any column types or sizes
SELECT TOP 0 KeyNm
INTO #MyTempTable
FROM dbo.MyDataTable2
-- Required to prevent IDENTITY_INSERT error
SET IDENTITY_INSERT #MyTempTable ON
IF #something = 1
BEGIN
-- Insert the actual rows required into the (currently empty) temp table
INSERT INTO #MyTempTable (KeyNm)
SELECT KeyNm
FROM dbo.MyDataTable2
WHERE CatNum = 2
END
ELSE
BEGIN
-- Insert the actual rows required into the temp table
INSERT INTO #MyTempTable (KeyNm)
SELECT KeyNm
FROM dbo.MyDataTable2
WHERE CatNum = 8
END
SET IDENTITY_INSERT #MyTempTable OFF
Temp tables are not dropped automatically at the end of a query, only when the current connection to the DB is dropped or you explicitly delete them with DROP TABLE #columntable
Either test for the existence of the table at the start of the query or alwayas delete it at the end (preferably both)
EDIT: As Matrin said in his comment, this is actually a parse error. You get the same error if you only parse the SQL as when you execute it.
To test that out I split up your query and tried:
if exists (select 1 from emp where id = 6)
create table #columntable (newcolumns varchar(100))
GO
if not exists (select 1 from emp where id = 6)
create table #columntable (oldcolumns varchar(100))
GO
The parser is happy with that. Interestingly if you change to using non-temp tables the original query parses fine (I realise the problems that would create, I was just interested to find out why the query would not parse).
This also occurs if you create the tables with SELECT INTO...as in
IF OBJECT_ID('tempdb..#MyTempTable', 'U') IS NOT NULL
DROP TABLE #MyTempTable
SELECT TOP 1 #MyVariable = ScaleValue
FROM MyDataTable1
WHERE ProductWeight > 1000
IF #MyVariable = 1
BEGIN
SELECT KeyNm
INTO #MyTempTable
FROM dbo.MyDataTable2
WHERE CatNum = 2
END
ELSE
BEGIN
SELECT KeyNm
INTO #MyTempTable
FROM dbo.MyDataTable2
WHERE CatNum = 8
END
The parser should not even attempt to detect this because, in many cases, it would be impossible for the parser to determine if the table would already exist. The code above is a perfect example...there would be no way for the parser to determine the value of #MyVariable.
I hope that someone has informed MS of this bug (I don't have their ear).
You can check if it exists by doing:
IF OBJECT_ID('tempdb..#columntable') IS NOT NULL
BEGIN
DROP TABLE #columntable
PRINT 'Dropped table...'
END
Use global temp tables and wrap the select in exec.
Example:
Fail
declare #a int = 1
if object_id('tempdb..##temp') is not null drop table ##temp
if(#a = 1) select * into ##temp from table_1
else if(#a = 2) select * into ##temp from table_2
Win
declare #a int = 1
if object_id('tempdb..##temp') is not null drop table ##temp
if(#a = 1) exec('select * into ##temp from table_1')
else if(#a = 2) exec('select * into ##temp from table_2')
This will fool the buggy parser that is trying to be smarter than it is.
And Microsoft - please fix this.
The error is wrong, remove the if clause and it runs through fine. Thus the problem is in the exists:
if object_id('tempdb..#columntable') is not null
begin
drop table #columntable
end
create table #columntable (oldcolumns varchar(100))
Well I got the answer...
As Martin said this is a parse/compile issue. So I Tried changing my script as below
if exists (select 1 from emp where eid = 6)
begin
if object_id('tempdb..#columntable') is not null
begin
drop table #columntable
end
create table #columntable (oldcolumns varchar(100))
end
go
if exists (select 1 from emp where eid = 1)
begin
if object_id('tempdb..#columntable') is not null
begin
drop table #columntable
end
create table #columntable (newcolumns varchar(100))
end
And this worked for me.
I have been experiencing this issue. My query consisted of several joined SELECT statements in the form of:
DROP TABLE IF EXISTS ##TempTableName
SELECT statement ...
So, every time I tried to alter SQL code I would get the above error. I have changed all my temp tables from ##global to #local and now I am able to alter my SQL as many times as needed. So the example above would become:
DROP TABLE IF EXISTS #TempTableName
SELECT statement ...