Deletion\Creation of Temp tables in SQL Server 2008 - sql

I have SQL code like this
IF Object_id('tempdb..#empDate) IS NOT NULL
DROP TABLE #empDate
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
After the above code some more lines of SQL follow and then it is repeated.
I get the following error.
Msg 2714, Level 16, State 1, Line 589
There is already an object named '#empDate' in the database.
I replaced the
IF Object_id('tempdb..#empDate) IS NOT NULL
with
IF Object_id('tempdb..#empDate%) IS NOT NULL
As it is written on the forums that SQL Server appends number to the subsequent temp table(s).
Source:
Check if a temporary table exists and delete if it exists before creating a temporary table
http://blog.sqlauthority.com/2009/05/17/sql-server-how-to-drop-temp-table-check-existence-of-temp-table/
http://blog.sqlauthority.com/2009/03/29/sql-server-fix-error-msg-2714-level-16-state-6-there-is-already-an-object-named-temp-in-the-database/
I am using Microsoft SQL Server 2008 on Windows 7 Enterprise.
I am not able to understand the cause of the error.
Please help.

Sample One
This will fail......
Executing the same code again, will throw the error you are getting now
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
Sample Two (Fixed)
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO --<-- Adding this Batch Separator will eliminate the Error
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
Test
If you try Executing the following Statements in ONE BATCH they will fail even though there isnt any table at all with the name #empDate, it will not even execute the very 1st Create table Statement. and will throw an error.
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
DROP TABLE #empDate
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
But if you separate all the statement in separate batches they will be executed successfully something like this..
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO
DROP TABLE #empDate
GO
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO

I would just drop your table without any pre-checks.
Then write/run the script clean.
Once done using the temp table, drop it at the end of your script.
So run this unconditionally
DROP TABLE #empDate
Then write/run your script and make sure you have this line at the end of your script.

pass database name with object_id
example :
DECLARE #db_id int;
DECLARE #object_id int;
SET #db_id = DB_ID(N'AdventureWorks2012');
SET #object_id = OBJECT_ID(N'AdventureWorks2012.Person.Address');
IF #db_id IS NULL
BEGIN;
PRINT N'Invalid database';
END;
ELSE IF #object_id IS NULL
BEGIN;
PRINT N'Invalid object';
END;
ELSE
BEGIN;
SELECT * FROM sys.dm_db_index_operational_stats(#db_id, #object_id, NULL, NULL);
END;
GO

Related

Atomically INSERT+SELECT or SELECT row (based on UNIQUE column)

My table is created as follows:
CREATE TABLE StackFunctionID
(
m_FunctionID int PRIMARY KEY IDENTITY,
m_GroupID int DEFAULT 0 NOT NULL,
m_Function varchar(256) UNIQUE NOT NULL,
);
GO
CREATE TRIGGER INSERT_MakeGroupID ON StackFunctionID AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
UPDATE StackFunctionID
SET StackFunctionID.m_GroupID = INSERTED.m_FunctionID
FROM StackFunctionID
INNER JOIN INSERTED ON (StackFunctionID.m_FunctionID = INSERTED.m_FunctionID)
END;
Now I'm trying to write a query for Sql Server 2008 that will
If m_Function does not exist, create it, and return m_FunctionID, m_GroupID
If m_Function exists, return m_FunctionID, m_GroupID
Perform it atomically
After much trying, this is what worked for the last years:
DECLARE #Results TABLE(m_FunctionID INT, m_GroupID INT); -- trash use
DECLARE #dummy1 int; -- trash use
MERGE INTO StackFunctionID WITH(HOLDLOCK) AS Target -- WITH(HOLDLOCK) for thread safety
USING (VALUES(null)) AS dummy2(dummy3) -- syntax requires USING
ON Target.m_Function = #m_Function
WHEN MATCHED THEN
UPDATE SET #dummy1 = 0 -- syntax requires something in 'WHEN MATCHED', which is needed for OUTPUT
WHEN NOT MATCHED THEN
INSERT(m_Function) VALUES(#m_Function)
OUTPUT inserted.m_FunctionID, inserted.m_GroupID
INTO #Results; -- Having a trigger requires 'INTO'
SELECT * FROM #Results -- Having a trigger requires 'INTO'
However, there was a bug: when a row is INSERTED, OUTPUT returns m_GroupID=0
Questions:
How do I always get correct m_GroupID ?
Is it possible to achieve the goal with a simpler query? (because current one is really hard to understand with all those "syntax requirements")
Relying on UNIQUE m_Function use TRY CATCH to INSERT and then SELECT.
Demo
CREATE TABLE StackFunctionID
(
m_FunctionID int PRIMARY KEY IDENTITY,
m_GroupID int DEFAULT 0 NOT NULL,
m_Function varchar(256) UNIQUE NOT NULL,
);
INSERT StackFunctionID(m_Function)
VALUES ('a'), ('b');
SELECT * FROM StackFunctionID;
DECLARE #m_Function varchar(256) = 'a';
BEGIN TRY
INSERT StackFunctionID(m_Function)
VALUES ( #m_Function);
END TRY
BEGIN CATCH
PRINT 'Already exists';
END CATCH
SELECT m_FunctionID, m_GroupID
FROM StackFunctionID
WHERE m_Function = #m_Function;

How can I pass tables to stored procedures?

I have a table of data like this, and one procedure is going to populate data in it like this,
DECLARE #ClaimChanges TABLE (
ChangeType NVARCHAR(10)
,contract_id int NOT NULL
,dispatch_id int NOT NULL
,dispatch_claim_id int NOT NULL
,item_no VARCHAR(100) NULL
,old_units VARCHAR(100) NULL
);
I would then like to pass that data to a different stored procedure which would be defined like this,
CREATE procedure [dbo].[ct_audit_oncost](
#table TABLE readonly,
#OutValue nvarchar(255) = null output
)
as
-- some stuff
go
I gather this is not possible as I am getting an error,
Incorrect syntax near the keyword 'TABLE'.
Table valued parameters are supported since 2008 version.
However, you can't just pass any table you want, first you need to define a user defined table type:
CREATE TYPE dbo.MyUDT as TABLE
(
ChangeType NVARCHAR(10)
,contract_id int NOT NULL
,dispatch_id int NOT NULL
,dispatch_claim_id int NOT NULL
,item_no VARCHAR(100) NULL
,old_units VARCHAR(100) NULL
)
Then you can use it in your stored procedure:
CREATE procedure [dbo].[ct_audit_oncost]
(
#table dbo.MyUDT readonly,
#OutValue nvarchar(255) = null output
)
as
-- some stuff
go
Please note you should also use it to declare the table to send to the database:
DECLARE #Out nvarchar(255)
DECLARE #ClaimChanges as dbo.MyUdt
INSERT INTO #ClaimChanges (ColumnsList) VALUES (ValuesList)
EXEC ct_audit_oncost #ClaimChanges, #Out output

T-SQL can't excute my procedure

My code:
CREATE TABLE test (id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
text VARCHAR(255)
);
GO
CREATE PROCEDURE testProc(#string VARCHAR(255))
AS
BEGIN
INSERT INTO test (text) VALUES (#string);
SELECT * FROM test;
END
GO
EXEC testProc('Test01')
The error I get after running it:
Incorrect syntax near 'Test01'.*
I want to insert 'Test01' into my table test with the help of the proc testProc, but it doesn't work.
You just need to omit the parentheses.
EXEC testProc #string = 'Test01';

TRY...CATCH doesn't seem to work

I have the following piece of code that's just to make sure that the temporary table doesn't exist. If the table exist I want to truncate it.
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
) --I create this just to test my try-catch
BEGIN TRY
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
)
END TRY
BEGIN CATCH
PRINT N'#LookupLinks already existed and was truncated.';
TRUNCATE TABLE #LookupLinks
END CATCH
What I want this to do:
The temp-table is created
Attempt to create it again
error sends us into the catch
table is truncated and everything continues as normal
What happens:
ERROR: There is already an object named '#LookupLinks' in the database.
What am I doing wrong here?
This is because SQL Server parses and validates the whole batch. So when parsing the second CREATE TABLE statement, it errors out saying:
There is already an object named '#LookupLinks' in the database.
See this example:
IF 1 = 1 BEGIN
CREATE TABLE #temp(col INT)
END
ELSE BEGIN
CREATE TABLE #temp(col INT)
END
It produces an error saying:
There is already an object named '#temp' in the database.
The workaround is to use Dynamic SQL.
-- CREATE the table for testing
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL
DROP TABLE #LookupLinks
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
)
-- Final query
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL BEGIN
TRUNCATE TABLE #LookupLinks
PRINT N'#LookupLinks already existed and was truncated.'
END
ELSE BEGIN
DECLARE #sql NVARCHAR(MAX) = ''
SELECT #sql = '
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
)'
EXEC sp_executesql #sql
PRINT N'#LookupLinks was created.'
END
If you do not have the first CREATE TABLE statement,your query will work just fine. Or if you put a GO before the BEGIN TRY.
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL
DROP TABLE #LookupLinks -- DROP FIRST
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
) --I create this just to test my try-catch
GO
BEGIN TRY
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
)
END TRY
BEGIN CATCH
PRINT N'#LookupLinks already existed and was truncated.';
TRUNCATE TABLE #LookupLinks
END CATCH
Still, it's because SQL server parses and validates the whole batch. The GO statement will put the statements into their own batches, thus the error is now not happening.
Even CeOnSql's answer will work fine.
I think what you really want to achieve is this:
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL --Table already exists
BEGIN
TRUNCATE TABLE #LookupLinks
PRINT N'#LookupLinks already existed and was truncated.';
END
ELSE
BEGIN
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
)
END
TRY CATCH is for run time error. What you are getting is a compile time error. Add a PRINT 1 before your statement and you'll see that nothing is getting executed.
print 1
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
);
BEGIN TRY
CREATE TABLE #LookupLinks(
[SyncID] uniqueidentifier,
[Name] nvarchar(50),
[SQLTable] nvarchar(50)
);
END TRY
BEGIN CATCH
PRINT N'#LookupLinks already existed and was truncated.';
TRUNCATE TABLE #LookupLinks
END CATCH

Drop temp table if it exists

Friends,
I am creating a temp table. The script may be run several times so I need to check if the temp table exist then drop it. I have the written the code below but I get an error when running the script twice, that the table already exists:
There is already an object named '#lu_sensor_name_19' in the database.
It appears that IF OBJECT_ID('alarm..#lu_sensor_name_19') IS NOT NULL does not return true when the tablle is not null. What am I doing wrong?
IF OBJECT_ID('alarm..#lu_sensor_name_19') IS NOT NULL
BEGIN
DROP TABLE #lu_sensor_name_19
END
CREATE TABLE #lu_sensor_name_19(
sensorname_id int NOT NULL,
sensorname nvarchar(50) NOT NULL,
paneltype_id smallint NOT NULL,
panel_version_id int NULL,
prefix_allowed tinyint NOT NULL,
base_allowed tinyint NOT NULL,
suffix_allowed tinyint NOT NULL,
key_value int NULL,
sort_index int NULL,
device_allowed tinyint NOT NULL,
sensor_name_group_id smallint NOT NULL,
)
Temp #Tables are created in tempdb. Try this:
IF OBJECT_ID('tempdb..#lu_sensor_name_19') IS NOT NULL
BEGIN
DROP TABLE #lu_sensor_name_19
END
CREATE TABLE #lu_sensor_name_19...
SQL Server 2016 added the ability to do the drop in one line:
DROP TABLE IF EXISTS #lu_sensor_name_19
CREATE TABLE #lu_sensor_name_19...
Use this.
IF OBJECT_ID('tempdb.dbo.##myTempTable', 'U') IS NOT NULL
BEGIN
DROP TABLE ##myTempTable;
--DROP TABLE ##tempdb.dbo.myTempTable;
/* Above line commented out, because it generates warning:
"Database name 'tempdb' ignored, referencing object in tempdb.",
which is a pain in the neck if you are using a temp table to generate SQL code,
and want to print the code to the screen.*/
END;
GO
CREATE TABLE ##myTempTable(
FooBar nvarchar(128) not null,
);
And, in SQL Server 2016, you can write:
DROP TABLE IF EXISTS ##myTempTable