Dependent object in the stored procedure is dropped and recreated again - sql

I am trying to test a scenario when the dependent object in a stored procedure is dropped and recreated again.
I need a way to re-compile the stored procedure, without recreating it.
CREATE TABLE t1
(
c1 int
)
CREATE PROCEDURE tst_Proc
AS
BEGIN
INSERT INTO t1
VALUES (1)
END
DROP TABLE t1
CREATE TABLE t1
(
c1 int
)
Now the tst_Proc will be in invalid state, as the table t1 was dropped and recreated again.
Is there any way I can recompile the stored procedure - so that the object becomes valid?
I don't want to alter and recreate the stored procedure, as there is no change in the definition.

Related

Insert data into a Temporary Table from a Stored Procedure

I have a stored procedure called Sp_Ejecucion inside it create a temporary table with the following structure:
CREATE TABLE #CambioResult (FOL INT IDENTITY, RESULT INT)
and after that command to run another Sp as follows
BEGIN TRAN T1
DECLARE #vnCambiaRollTurnoResult INT = 0,
#vnReacomodoMarcajesResult INT = 0,
#Result INT = 0
BEGIN TRY
exec nsp_Exec #nClaEmp = #pnClaEmpresa,
#nClaTrab = #pnClaTrab,
END TRY
BEGIN CATCH
GOTO RETURN_ERROR
END CATCH
And the inside of the second stored I want to insert data to the table created in the first stored, How can I do it? what I have intended is the following:
INSERT INTO OBJECT_ID('tempdb..#CambioResult')
select #Error
pero marca error en esta parte OBJECT_ID
As you are inserting within the nested procedure, you will be able to reference the parent procedure temporary table #CambioResult inside nested procedure.
You have to change your INSERT statement in the nested procedure: nsp_Exec as given below:
INSERT INTO #CambioResult
SELECT ....
About Temporary table scope, reference msdn
Temporary tables are automatically dropped when they go out of scope,
unless explicitly dropped by using DROP TABLE:
A local temporary table created in a stored procedure is dropped automatically when the stored procedure is finished. The table can be
referenced by any nested stored procedures executed by the stored
procedure that created the table. The table cannot be referenced by
the process that called the stored procedure that created the table

Reduce duplication of creation of SQL temp tables

I have multiple (more than 12) SQL Stored Procedures that setup the same set of temp tables at the start of each procedure. When one of these tables needs modified I need to go make a change in each of those Stored Procedures to match. The temp tables are expected to exist by other stored procedures later in the process. I have no ability to change the process or the flow of these stored procedures or the fact of using these as temp tables, I am coming at it from a DRY approach and looking for a way to consolidate the creation of these shared temp tables into a reusable piece of code so that when changes are needed I can do it in 1 file and reduce the amount of duplication happening today.
Example of the stored procedure
CREATE OR ALTER PROCEDURE [dbo].[procedureName]
#inputs ...
AS
BEGIN
DROP TABLE IF EXISTS #Table1
CREATE TABLE #Table1 (...)
DROP TABLE IF EXISTS #Table2
CREATE TABLE #Table2 (...)
...
DROP TABLE IF EXISTS #Table10
CREATE TABLE #Table10 (...)
...
INSERT INTO #Table5
SELECT * FROM data
...
END

Access #TempTable declared in child procedure in parent procedure

I have nested stored procedures and I need to create a LOCAL TEMP TABLE in child procedure and be able to use it in the parent procedure.
EX:
Parent procedure:
EXEC ChildProcedure
SELECT * FROM #TempTable
Child procedure:
CREATE TABLE #TempTable (Field1 VARCHAR(1000),Field2 VARCHAR(1000))
INSERT INTO #TempTable (Field1,Field2) VALUES ('1','2')
When I try this, SQL says:
Invalid Object Name '#TempTable'
Is there any way to achieve this without GLOBAL TEMP TABLES ?
Well I think I finally found the answer to my question in https://msdn.microsoft.com/en-us/library/ms174979.aspx.
A local temporary table created in a stored procedure is dropped automatically when the stored procedure is finished. The table can be referenced by any nested stored procedures executed by the stored procedure that created the table. The table cannot be referenced by the process that called the stored procedure that created the table.
So the answer to my own question is NO. I can't do that in that way.
The best approach (as #Damien_The_Unbeliever said) is to create the table in the parent procedure and populate it inside the child procedure.
Instead of Procedure you can create a table valued function like this and use a
Create Function ChiledFunction ()
Returns #TempTable Table (Field1 VARCHAR(1000),Field2 VARCHAR(1000)) AS
Begin
INSERT INTO #TempTable (Field1,Field2) VALUES ('1','2')
Return
end
and parent procedure is here
Create Procedure ParentProc
As
begin
select * from dbo.ChiledFunction()
end

StoredProc manipulating Temporary table throws 'Invalid column name' on execution

I have a a number of sp's that create a temporary table #TempData with various fields. Within these sp's I call some processing sp that operates on #TempData. Temp data processing depends on sp input parameters. SP code is:
CREATE PROCEDURE [dbo].[tempdata_proc]
#ID int,
#NeedAvg tinyint = 0
AS
BEGIN
SET NOCOUNT ON;
if #NeedAvg = 1
Update #TempData set AvgValue = 1
Update #TempData set Value = -1;
END
Then, this sp is called in outer sp with the following code:
USE [BN]
--GO
--DBCC FREEPROCCACHE;
GO
Create table #TempData
(
tele_time datetime
, Value float
--, AvgValue float
)
Create clustered index IXTemp on #TempData(tele_time);
insert into #TempData(tele_time, Value ) values( GETDATE(), 50 ); --sample data
declare
#ID int,
#UpdAvg int;
select
#ID = 1000,
#UpdAvg = 1
;
Exec dbo.tempdata_proc #ID, #UpdAvg ;
select * from #TempData;
drop table #TempData
This code throws an error: Msg 207, Level 16, State 1, Procedure tempdata_proc, Line 8: Invalid column name "AvgValue".
But if only I uncomment declaration AvgValue float - everything works OK.
The question: is there any workaround letting the stored proc code remain the same and providing a tip to the optimizer - skip this because AvgValue column will not be used by the sp due to params passed.
Dynamic SQL is not a welcomed solution BTW. Using alternative to #TempData tablename is undesireable solution according to existing tsql code (huge modifications necessary for that).
Tried SET FMTONLY, tempdb.tempdb.sys.columns, try-catch wrapping without any success.
The way that stored procedures are processed is split into two parts - one part, checking for syntactical correctness, is performed at the time that the stored procedure is created or altered. The remaining part of compilation is deferred until the point in time at which the store procedure is executed. This is referred to as Deferred Name Resolution and allows a stored procedure to include references to tables (not just limited to temp tables) that do not exist at the point in time that the procedure is created.
Unfortunately, when it comes to the point in time that the procedure is executed, it needs to be able to compile all of the individual statements, and it's at this time that it will discover that the table exists but that the column doesn't - and so at this time, it will generate an error and refuse to run the procedure.
The T-SQL language is unfortunately a very simplistic compiler, and doesn't take runtime control flow into account when attempting to perform the compilation. It doesn't analyse the control flow or attempt to defer the compilation in conditional paths - it just fails the compilation because the column doesn't (at this time) exist.
Unfortunately, there aren't any mechanisms built in to SQL Server to control this behaviour - this is the behaviour you get, and anything that addresses it is going to be perceived as a workaround - as evidenced already by the (valid) suggestions in the comments - the two main ways to deal with it are to use dynamic SQL or to ensure that the temp table always contains all columns required.
One way to workaround your concerns about maintenance if you go down the "all uses of the temp table should have all columns" is to move the column definitions into a separate stored procedure, that can then augment the temporary table with all of the required columns - something like:
create procedure S_TT_Init
as
alter table #TT add Column1 int not null
alter table #TT add Column2 varchar(9) null
go
create procedure S_TT_Consumer
as
insert into #TT(Column1,Column2) values (9,'abc')
go
create procedure S_TT_User
as
create table #TT (tmp int null)
exec S_TT_Init
insert into #TT(Column1) values (8)
exec S_TT_Consumer
select Column1 from #TT
go
exec S_TT_User
Which produces the output 8 and 9. You'd put your temp table definition in S_TT_Init, S_TT_Consumer is the inner query that multiple stored procedures call, and S_TT_User is an example of one such stored procedure.
Create the table with the column initially. If you're populating the TEMP table with SPROC output just make it an IDENTITY INT (1,1) so the columns line up with your output.
Then drop the column and re-add it as the appropriate data type later on in the SPROC.
The only (or maybe best) way i can thing off beyond dynamic SQL is using checks for database structure.
if exists (Select 1 From tempdb.sys.columns Where object_id=OBJECT_ID('tempdb.dbo.#TTT') and name = 'AvgValue')
begin
--do something AvgValue related
end
maybe create a simple function that takes table name and column or only column if its always #TempTable and retursn 1/0 if the column exists, would be useful in the long run i think
if dbo.TempTableHasField('AvgValue')=1
begin
-- do something AvgValue related
end
EDIT1: Dang, you are right, sorry about that, i was sure i had ... this.... :( let me thing a bit more

how can i drop a table which i have declared in my SP

like i declared a table...
declare #tempTable TABLE
(Id bigint identity(1,1),
bKey int,
DateT DateTime,
Addres nvarchar(max),
unit bigint)
and i want to drop it...but im stucked coz drop table n truncate are not working.
ani ideaaa...???
Table variables only live while they are in scope, in your case for the duration of the stored procedure. It will delete itself once the procedure completes.
You might be thinking of a temporary table:
CREATE TABLE #MyTempTable
There are differences between temporary tables and table variables:
http://sqlnerd.blogspot.com/2005/09/temp-tables-vs-table-variables.html
A better link:
http://www.sql-server-performance.com/articles/per/temp_tables_vs_variables_p1.aspx
You don't need to drop table variables (i.e. those that start with #)
You've declared the table as a table variable. It will only exist for the duration of the stored procedure. When the procedure ends, it is automatically "dropped" (ceases to exist is more accurate, as it never really existed in the way other tables do). You cannot drop them manually.
You created a temporary table which is saved in a variable. It only exists as long as the store procedure is being executed. When the SP has finished the temporary table ceases to exists and it's being deleted automatically.
edit:
you could try testing it by running the stored procedure and then try to run a select query on your #tempTable
why do you want to drop a table variable? scope of table variable is in declare stored procedure only...
check this article... Table Variables In T-SQL
UPDATE
Use #temptable as suggested by #Adam...
Then TRUNCATE TABLE #temptable, instead of DROP TABLE; this way no need to recreate it within loop.
In your SP, this will remove all the values from your declared table
DELETE FROM #tempTable