Unexpected error on query - sql-server

When executing this code on SQL Server 2012 through SQL Server Management Studio:
PRINT 'Begin';
SELECT 1 A INTO #TEST;
DROP TABLE #TEST;
SELECT 1 A INTO #TEST;
I get the error
There is already an object named '#TEST' in the database.
and it doesn't even print 'Begin'.
What I am expecting is that the code prints 'Begin' and I have a #TEST table with one column called 'A' and one row containing '1'. Why is my expectation wrong?
Thanks
--- Update ---
By the way, this code returns the same error message:
IF OBJECT_ID('tempdb..#TEST') IS NOT NULL DROP TABLE #TEST
GO
PRINT 'Begin';
SELECT 1 A INTO #TEST;
DROP TABLE #TEST;
SELECT 1 A INTO #TEST;

Once you run the code once the temp table #TEST already exists. Once created it lasts until your session is over. You would need to drop it before you can run it again.
put this at the top and it will work:
IF OBJECT_ID('tempdb..#Test') IS NOT NULL DROP TABLE #TEST
GO
If this doesn't work then the problem then is that you are using the INTO statement twice. The second call is causing the error because #test would exist after the first into. It's kind of a bug with error checking SQL I guess. In order to get around it you either need to use a different temp table name on the second into or put a GO after the DROP table like this
PRINT 'Begin';
SELECT 1 A INTO #TEST;
DROP TABLE #TEST;
GO
SELECT 1 A INTO #TEST;
Alternatively you could just create the table first and then insert into them but then you lose the performance advantages of into - not sure if that is required or not.

Try this:
DROP TABLE #TEST;
PRINT 'Begin';
SELECT 1 A INTO #TEST;
DROP TABLE #TEST;
SELECT 1 A INTO #TEST;

Related

Creating temp tables in sybase

I am running into an issue with creating temp tables in Sybase db. We have a sql where we create a temp table, insert/update it and do a select * from it at the end of get some results. We are invoking this sql from the service layer using spring jdbc tmplate. The first run works fine, but the next subsequesnt runs fails with error
cannot create temporary table <name>. Prefix name is already in use by another temorary table
This is how I am checking if table exists:
if object_id('#temp_table') is not null
drop table #temp_table
create table #temp_table(
...
)
Anything I am missing here?
Might not be a great response, but I also have that problem and I have 2 ways around it.
1. Do the IF OBJECT_ID Drop Table as a separate execute prior to the query
2. Do the Drop Table without the IF OBJECT_ID() right after your query.
You are really close but temp tables require using the db name before too.
IF OBJECT_ID('tempdb..#Results') IS NOT NULL
DROP TABLE #Results
GO
It would be the same if you were checking if a user table in another database existed.
IF OBJECT_ID('myDatabase..myTable') IS NOT NULL
DROP TABLE myDatabase..myTable
GO
NOTE: A bit more info on BigDaddyO's first suggestion ...
The code snippet you've provided, when submitted as a SQL batch, is parsed as a single unit of work prior to the execution. Net result is that if #temp_table already exists when the batch is submitted, then the compilation of the create table command will generate the error. This behavior can be seen in the following example:
create table #mytab (a int, b varchar(30), c datetime)
go
-- your code snippet; during compilation the 'create table' generates the error
-- because ... at the time of compilation #mytab already exists:
if object_id('#mytab') is not NULL
drop table #mytab
create table #mytab (a int, b varchar(30), c datetime)
go
Msg 12822, Level 16, State 1:
Server 'ASE200', Line 3:
Cannot create temporary table '#mytab'. Prefix name '#mytab' is already in use by another temporary table '#mytab'.
-- same issue occurs if we pull the 'create table' into its own batch:
create table #mytab (a int, b varchar(30), c datetime)
go
Msg 12822, Level 16, State 1:
Server 'ASE200', Line 1:
Cannot create temporary table '#mytab'. Prefix name '#mytab' is already in use by another temporary table '#mytab'.
As BigDaddyO has suggested, one way to get around this is to break your code snippet into two separate batches, eg:
-- test/drop the table in one batch:
if object_id('#mytab') is not NULL
drop table #mytab
go
-- create the table in a new batch; during compilation we don't get an error
-- because #mytab does not exist at this point:
create table #mytab (a int, b varchar(30), c datetime)
go

Can SQL Server CONVERT null values from JAVA to 0?

Say I have a decimal column in database. I wanna pass a null value from java and convert it to 0 in sql. I've tried ticking off 'allow nulls' while passing null value from java but it gives me an error saying 'column does not allow nulls'. Can SQL Server automatically convert java null values to 0? I'm using SQL Server 2014. Thanks.
I would suggest adding an INSTEAD OF INSERT Trigger:
CREATE TRIGGER IOI_MyTable ON MyTable
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO MyTable
SELECT ISNULL(Col1, 0), ISNULL(Col2, 0), ...
FROM inserted
END;
GO
From Tyron78's answer,
I have used instead of trigger to catch insert statements into the table then change the null value to 0 using ISNULL().
But since my table has a lot of columns and I do not have time as of now to write it all down :), I had to put the data in a temporary table and DROP the identity column.
ALTER TRIGGER checkNull ON <table>
INSTEAD OF INSERT
AS
BEGIN
SELECT * INTO #tempTable FROM inserted
UPDATE #tempTable SET <column> = ISNULL(<column>,0)
ALTER TABLE #TempTable
DROP COLUMN id
INSERT INTO <table>
SELECT *
FROM #tempTable
END;
GO
However, I will mark Tyron78's as the solution because it is more understandable/debuggable

SQL Server Stored Procedure with multiple batches - reuse of temp table

I have a short SQL script which has been in use for a bit. It reuses a temp table within a script and has been working nicely.
Recently, I decided that I'm going to stick this whole thing into a procedure, though I had a surprise waiting for me - there's a use of the keyword GO in order to divide the script into two batches (that is how I was able to reuse the temp table) - which is why SQL Server is barking at me.
Here is a dumbed down script displaying the functionality of the script:
DROP TABLE IF EXISTS #temp;
SELECT
'john' AS first_name
,'doe' AS last_name
INTO #temp;
SELECT * FROM #temp
GO
TRUNCATE TABLE #temp;
DROP TABLE #temp;
SELECT
'jane' AS first_name
,'doe' AS last_name
INTO #temp;
Here's what I tried to do in the procedure, albeit unsuccessfully:
CREATE PROCEDURE #temp_proc
AS
BEGIN
DROP TABLE IF EXISTS #temp;
SELECT
'john' AS first_name
,'doe' AS last_name
INTO #temp;
SELECT * FROM #temp
GO
TRUNCATE TABLE #temp;
DROP TABLE #temp;
SELECT
'jane' AS first_name
,'doe' AS last_name
INTO #temp;
END
Here's the error message I get when I attempt to create the procedure:
Msg 102, Level 15, State 1, Procedure #temp_proc, Line 10 [Batch Start Line 0]
Incorrect syntax near '#temp'.
Msg 102, Level 15, State 1, Line 20
Incorrect syntax near 'END'.
Objective: I'd like to continue reusing the same temp table names, though I would like to stick all of this in a procedure. Any ideas?
You can't use GO in a stored procedure. If you remove it, your code should run as expected. Although there is no need to truncate the table if you drop it later.
sorry but no - you do not understand GO. It is a keyword that is understood and implemented by an application. It indicates to the application to take all preceding script text (until the beginning of the script or the previous GO) and send it to the db engine for execution. Your procedure creation script is interpreted and executed as 2 separate batches (which is why GO is called a batch separator). The first one is:
CREATE PROCEDURE #temp_proc
AS
BEGIN
DROP TABLE IF EXISTS #temp;
SELECT
'john' AS first_name
,'doe' AS last_name
INTO #temp;
SELECT * FROM #temp
GO
Followed by:
TRUNCATE TABLE #temp;
DROP TABLE #temp;
SELECT
'jane' AS first_name
,'doe' AS last_name
INTO #temp;
END
And notice that this is merely creating your procedure. It has nothing to do with how the procedure is executed. There is nothing to leverage here - you cannot divide your procedure definition or execution into batches using "go". So your idea and direction is, quite simply, impossible without a change. Dynamic sql is a possibility - but that is a level of complexity that will challenge and tax you.
Aside from removing the GOs in your code, you can't drop and recreate the same temp table in a stored procedure; SQL Server ignores the drop and attempts to create the same # table in the two SELECT INTO statements.

Truncate existing table within a stored procedure then insert fresh data

I have a stored procedure that returns a result set. After that I insert this result set into created real table. And then I am using that real table create SSRS reports.
So, something like this:
CREATE PROCEDURE Test
AS
DECLARE #TempTable TABLE(..)
INSERT INTO #TempTable
SELECT...
FROM ...
WHERE ...
SELECT * FROM #TempTable
--============================
INSERT INTO RealTable EXEC [dbo].[Test]
How can I modify this stored procedure so every time it executed it will truncate table with existing data and then insert a fresh one?
So I need something like that:
create procedure Test
as
TRUNCATE RealTable
DECLARE #TempTable TABLE(..)
INSERT INTO #TempTable
SELECT...
FROM...
WHERE...
SELECT * FROM #TempTable INTO RealTable
Or should I just create agent job that would run command something like:
Truncate Table RealTable
INSERT INTO RealTable EXEC [dbo].[Test]
Am I on a right way in terms of logic?
Dont TRUNCATE. Use a MERGE Statement.
CREATE PROCEDURE Test
AS
MERGE RealTable TRGT
USING SourceTable SRCE
ON SRCE.[Column] = TRGT.Column --use columns that can be joined together
WHEN MATCHED THEN UPDATE
SET TRGT.Column1 = SRCE.Column1,
TRGT.Column2 = SRCE.Column2
....................
WHEN NOT MATCHED BY TARGET THEN INSERT
VALUES
(
SRCE.Column1,
SRCE.Column2,
.....................
)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
What's the purpose of the truncate if you are inserting the same data?
What should happen if you have more then 1 concurrent user?
another thing you can do:
1.
insert into TargetTable
select * from SourceTable
2.
rebuild indexes on TargetTable
3.
exec sp_rename SourceTable, SourceTable_Old
exec sp_rename TargetTable, SourceTable
drop table SourceTable_Old
this is an old way of entire table data refresh without much impact, when table variable was not an option.
this is what you probably need as you are directly inserting from #TempTable to RealTable.
create procedure Test
as
BEGIN
TRUNCATE TABLE RealTable
INSERT INTO RealTable
SELECT...
FROM someothertable
WHERE...
END

insert return data from SP to temp table

I have a stored proc, SP1, which executes and does select on one table. Now i have the need to insert that data in another table. I dont want to duplicate the code so i thought of inserting the data returned by the SP1 in the temp table so i can do some processing on it and save it.
I tried INSERT INTO #tmp; exec dbo.Sp1; but it gives me an error saying Invalid object name '#tmp'.. Isnt there a way i can create this table dynamically? Is there a better solution to this problem?
The temp table has to exist before you can use insert into exec.
This is not such a draw back as it first seems as any changes to the procedure result set will likely brake your code.
first run this:
create proc MySelect
as
begin
select 1 as myColumn1, 2 as mycolumn2
end
and then this:
create table #tmp(
col_1 int,
col_2 int)
insert into #tmp exec MySelect
select * from #tmp

Resources