Error renaming a temporary table - sql-server

Is it possible to rename a temporary table?
create table #t (id integer);
execute tempdb.sys.sp_rename '#t', '#s';
An invalid parameter or option was specified for procedure 'sys.sp_rename'
The proposed solution by #Michel, inserting into another temp table and dropping the original, works but I guess how expensive it is.

Tempdb doesn't have the sp_rename procedure. What you could do is to create a new temptable with the contents of your old one
Something like this
select * into #NewName from #OldName
drop table #OldName

Related

Create / Alter procedure referencing non-existing table or view

According to MSDN:
A procedure can reference tables that do not yet exist. At creation
time, only syntax checking is performed. The procedure is not compiled
until it is executed for the first time. Only during compilation are
all objects referenced in the procedure resolved. Therefore, a
syntactically correct procedure that references tables that do not
exist can be created successfully; however, the procedure fails at
execution time if the referenced tables do not exist.
I was always under the impression that referenced tables are checked. For example if you reference an incorrect column in an existing view it complains at compile time:
So what is going on here, why are columns checked within the procedure but not views / tables?
The document is referencing that, at the time to Stored Procedure is created, it isn't validated. Take this batch:
USE Sandbox;
GO
CREATE PROC dbo.MyProc #ID int AS
BEGIN
SELECT *
FROM dbo.MyTable
WHERE ID = #ID;
END;
GO
CREATE TABLE dbo.MyTable (ID int,
SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
(2,'asdkj');
GO
EXEC dbo.MyProc 1;
GO
DROP TABLE dbo.MyTable;
DROP PROC dbo.MyProc;
Notice that I CREATE dbo.MyProc before dbo.MyTable, even though it references that object. That's because the validity of the objects in the procedure isn't checked at the point the procedure is created or altered.
A VIEW on the other hand, is checked at the time that it is created.
CREATE TABLE dbo.MyTable (ID int,
SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
(2,'asdkj');
GO
--Fails
CREATE VIEW dbo.MyView AS
SELECT ID,
SomeValue,
SomeInt
FROM dbo.MyTable;
GO
--Fails
CREATE VIEW dbo.MyOtherView AS
SELECT *
FROM dbo.MyOtherTable;
GO
DROP TABLE dbo.MyTable;
Depending on the object type depends on what is validated and isn't when the DDL statement is issued.
Edit: It seems that what the OP is questioning is why do that get an error if the object does exist, but they reference a column that doesn't. For exmaple take the below batch:
USE Sandbox;
GO
CREATE TABLE dbo.MyTable (ID int,
SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
(2,'asdkj');
GO
CREATE PROC dbo.MyProc #ID int AS
BEGIN
SELECT ID,
SomeValue,
AnotherValue
FROM dbo.MyTable
WHERE ID = #ID;
END;
GO
DROP TABLE dbo.MyTable;
GO
DROP PROC dbo.MyProc;
GO
This fails as the column AnotherValue does not exist. This is actually covered in the very documentation you quote:
A procedure can reference tables that do not yet exist. At creation time, only syntax checking is performed.
It explicitly states you can reference a table that does not exist. It makes no mention of objects that don't, or (more specifically) columns in a table/object. Referencing a table that does exist will be validated at creation time.

SQL Server : what happens if I run the same stored procedure simultaneously that has a select into same temporary table

Any idea, what happen if I run same stored procedure (using jmeter) simultaneously,and in that stored procedure there are query
SELECT INTO #temp
Will the second stored procedure run after first stored procedure is done?
Or will the temp table be created twice (I heard there is local temp table in SQL Server)?
Sorry for the dumb question, I cannot find any answer on Google.
Thanks
A temporary table only exists in the scope it was created in (and "subscopes" of that scope) and only persist for the duration of that scope.
So, for example. If you were to run the below, you wouldn't get any errors:
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
That's because the table, #temp would only exist within the scope of the "dynamic" statement, and would cease to as soon as it completes.
On the other hand, something like the below would fail (This is wrong, see my edit at the bottom):
CREATE TABLE #temp (ID int);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
DROP TABLE #temp;
That's because the "dynamic" statement has access to the "outer" scope, and so would see that #temp already exists and generate an error.
Running 2 statements at the same time in the same connection isn't possible, so you won't be able to call the same Stored Procedure at the same time. This means that both will have different scopes, and will therefore reference they're own object #temp, that is specific to their scope.
You could again test this with a similar idea. Run the below, and then open a new connection and run it again (before the other is complete). You'll notice that they both succeed:
CREATE TABLE #temp (ID int);
WAITFOR DELAY '00:30'; --Waits 30 seconds
--While the WAITFOR happens, open the another connection and run all this SQL at the same time
DROP TABLE #temp;
Side note, Global Temporary tables do not behave the same way, but I specifically only reference temporary tables here, not global ones.
EDIT: Appears I am wrong, sort of, on inner scopes. You actually get some very odd behaviour. Take the below:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int); SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
This will return 2 datasets, one with no rows, one with 1 row. If, however, you remove the CREATE in the deferred statement then you get 1 row from both:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
This occurs on SQL Server 2019, but I sure I recall that this behaviour isn't how it was on previous versions. Perhaps I am recalling (very) old behaviour.

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

Compare tables columns(types,collation,nullable...) and update 2nd one according to found differences

I have two Dbs on the same server named 'DB_prod' and 'DB_test', and they are simply the same.
I need to assume that someone can modify table on 'DB_prod'. The script need to find all columns differences (types,collation,nullable,max length) + find new columns, and alter it to table on the 'DB_test'.
There are no relationships between tables.
First step is to find diffrences and I know how to accomplish this.
The secound step would be to move all chages to 'DB_test'.
The only idea I have for now is to use dynamic sql, so write diffrent table 'alters' and execute them in cursor.
Any other idea?
All work need to be done by procedure(s).
Thanks
A database-scoped trigger is probably what you're looking for. You can use it to record the alter table statements to a table TriggerLog and then run your stored procedure to execute the statements on your test table.
--Table to hold your event data.
CREATE TABLE TriggerLog
(
Event_Data NVARCHAR(MAX),
Username NVARCHAR(250),
Event_Date DATETIME
)
CREATE TRIGGER trg_alter_table ON DATABASE --database level trigger
FOR ALTER_TABLE
AS
INSERT TriggerLog
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)'),
COALESCE(SUSER_SNAME(),USER_NAME()),
GETDATE();
GO
ALTER TABLE ProdTable
ADD column1 VARCHAR(100);
SELECT *
FROM triggerlog
Results:
Event_data Username Event_Date
------------------------------------------------------------------------------------------
ALTER TABLE ProdTable ADD column1 VARCHAR(100); Domain\User 2015-03-16 09:29:47.387

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