I was keen to have some creation of SQL Server temp tables occur in a sub process to break up the stored procedure into parts rather than one big monolithic process.
i.e.
CREATE PROCEDURE dbo.P422270HRF605CreateTempTables
AS
IF OBJECT_ID('tempdb..#tmpState') IS NOT NULL
DROP TABLE #tmpState
CREATE TABLE #tmpState
(
StateID VARCHAR(8) NOT NULL,
Include VARCHAR(1) NOT NULL
)
GO
And I have another procedure call this and then use the temp tables ..
ALTER PROCEDURE Membership.GenerateHRF605Data
#FromDate DateTime,
#ToDate DateTime,
#MemberNo INT
AS
BEGIN
-- create all the temp tables required for HRF 605 processing
EXEC dbo.P422270HRF605CreateTempTables
INSERT INTO #tmpState
SELECT StateID, Include = 'N'
FROM dbo.States
UNION
SELECT 'Overseas', 'N'
UNION
SELECT 'Unknown', 'N'
but this seems to fail at runtime:
EXEC [Membership].[GenerateHRF605Data] #FromDate='20190901', #ToDate='20190930', #MemberNo=90001
I get this error:
Msg 208, Level 16, State 0, Procedure Membership.GenerateHRF605Data, Line 125 [Batch Start Line 0]
Invalid object name '#tmpState'.
Maybe SQL Server doesn't allow for the creation of temp tables in a called procedure and use of them in calling procedure?
Related
I have a stored procedure in Sybase, it's called by the Java code on a row by row insertion, how do I find out whether this SP is locking table or locking row? To check the underlying table properties or the SP itself?
CREATE PROCEDURE dbo.sp1
(#id_code varchar(10),
#position_id numeric(10,0) OUTPUT
)
AS
BEGIN
BEGIN TRANSACTION
INSERT INTO abc..table1(
id_code,
position_id
)
values (
#id_code
#position_id
)
COMMIT
SELECT #position_id = ##identity
END
go
EXEC sp_procxmode 'dbo.sp1', 'unchained'
go
IF OBJECT_ID('dbo.sp1') IS NOT NULL
PRINT '<<< CREATED PROCEDURE dbo.sp1 >>>'
ELSE
PRINT '<<< FAILED CREATING PROCEDURE dbo.sp1 >>>'
The lock scheme for a table can be determined using the lockscheme() built in command.
lockscheme('tableName')
You can also specify obj_id and dbid.
ASE 16 Documentation: lockscheme
I want to fetch data from one table and insert into another using stored procedure.
Below is my code:
CREATE PROCEDURE uspInitiateSRFWorkFlow
#WFPolicyID nvarchar(50) = null
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO ProjectWorkflowAgg
SELECT * FROM WFPolicyDetails where MasterCode = #WFPolicyID ORDER BY Priority ASC;
END
GO
Error is :
Msg 2809, Level 18, State 1, Line 1
The request for procedure 'WFPolicyDetails' failed because 'WFPolicyDetails' is a table object.
It better to specify Columns in insert and select statment..
CREATE PROCEDURE uspInitiateSRFWorkFlow
#WFPolicyID nvarchar(50) = null
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO ProjectWorkflowAgg(Column1...,Column)
SELECT Column1...,Column FROM WFPolicyDetails where MasterCode = #WFPolicyID ORDER BY Priority ASC;
END
GO
To fetch the data from one table and enter it to another it is best to use a trigger. To learn how to use the triggers, here is the link https://msdn.microsoft.com/en-IN/library/ms189799.aspx.
Hopefully it may help with your problem. Best of luck!!
I just started working with stored procedures. I have 2 problems.
When I create an object with a new name, it works successfully BUT no table shows up... where is it?
Second when I execute again I get an error
There is already an object named '##sp_MemberCertificates' in the database
I'm trying to fix this by using:
IF (SELECT object_id('TempDB..##Temp')) IS NOT NULL
BEGIN
DROP TABLE ##Temp
END
But I don't know how to use this exactly...
CREATE PROCEDURE ##sp_MemberCertificates (#MemberId int, #FromDate Varchar (30), #ToDate Varchar (30))
AS
SELECT Email,
CertificateNumber,
Mem_Name,
Mem_Address,
Mem_city,
Mem_state,
Mem_cellno,
Amount,
DateValid,
DateSent
--Use INTO ?? --
FROM UnitedDiningClub.dbo.UDC_Certificates
JOIN UnitedDiningClub.dbo.UDC_Member m
ON m.Mem_ID = UDC_Certificates.MemberId
JOIN UnitedDiningClub.dbo.UDClub_Client c
ON c.ClientId = UDC_Certificates.RestaurantId
WHERE MemberId = #MemberId
ORDER BY MemberId
EXEC ##sp_MemberCertificates #MemberId = '1', #FromDate = '2011-07-19 00:00:00.000', #ToDate = '2015-07-19 00:00:00.000'
go
Thanks for the help, please let me know if there more problems with the code, I am trying to learn.
use this to execute your stored procedure
rename your procedure to usp_MemberCertificates '##sp_MemberCertificates' is used for temp sp
remove exec statement from your procedure
use exec statement like this
EXEC usp_MemberCertificates 1, '2011-07-19 00:00:00.000', '2015-07-19 00:00:00.000'
you don't have to mention the variable name
moreover 1 is integer whereas you were sending a varchar type
also once you create a procedure you should add Alter instead of Create to so that it doesnt throw this error
There is already an object named '##sp_MemberCertificates' in the
database
You create global temporary stored procedure (using prefix ##). This stored procedure is visible from all the sessions in the server. The stored procedure is in Temp DB (as you already mentioned). So you can add DROP PROCEDURE, not drop table as in your example. Also you have to DROP ##sp_MemberCertificates, not ##Temp.
Second when creating procedure the script must finish with GO, but before you try to execute (EXEC ##sp_MemberCertificates #MemberId = '1', #FromDate = '2011-07-19 00:00:00.000' in your code). Also if you intend to use INTO (--Use INTO ?? -- in your code) you must drop table before that.
I wrote a stored procedure to insert future dates (excluding Sat and Sun) into a permanent table. The routine uses just one temp table. The purpose of this post is not to critique the Stored Procedure. Although, I am certain it could be improved. However, the purpose of this post is to analyze why the stored procedure is throwing these errors when called under one set of circumstances and not others.
1 - Here are the errors I receive
Msg 207, Level 16, State 1, Procedure MAKE_FUTURE_DATES, Line 25
Invalid column name 'tdate'.
Msg 207, Level 16, State 1, Procedure MAKE_FUTURE_DATES, Line 31
Invalid column name 'wday'.
2 - Here is the stored procedure
ALTER PROCEDURE [dbo].[MAKE_FUTURE_DATES] (#STARTDATE DATE)
AS
BEGIN
-- We need to populate FUTURE_DATES (table) with forward looking dates (week days only)
-- We do not consider/exclude holidays here. We just exclude Sat/Suns
-- Temp table to hold the dates and days of the week
CREATE TABLE #TMP_DATES(
[tdate] [date] NULL,
[wday] [varchar](10) NULL,
)
-- To generate 'enough' future dates loop up to 1199 days in the future
-- and insert dates that start with the current date and increase with each loop
DECLARE #Loop INT
SET #Loop = 0
WHILE #Loop < 1200
BEGIN
INSERT INTO #TMP_DATES (tdate) VALUES (DATEADD(weekday,#Loop,#STARTDATE))
SET #Loop = #Loop + 1
END
-- Now update the wday column with the weekday name so we can get rid of
-- Sat/Sun in the next step
UPDATE #TMP_DATES
SET wday = UPPER(LEFT(DATENAME(dw,tdate),3))
-- Get rid of Sat/Sun
DELETE FROM #TMP_DATES WHERE wday = 'SAT' or wday = 'SUN'
-- Now clear the final destination table
TRUNCATE TABLE FUTURE_DATES
-- Insert the weekday dates into future_dates
INSERT INTO FUTURE_DATES (fdate,wday)
SELECT tdate,wday FROM #TMP_DATES
DROP TABLE #TMP_DATES
3 - I have been calling the above stored procedure within another stored procedure as a SQL Server task in the background (via the SQL Server job scheduler) for about 6 months without any errors or problems. More recently, I created a new stored procedure, let's call it 'ABC', that calls a stored procedure that calls MAKE_FUTURE_DATEs.
4 - Here is the part I am trying to solve. When ABC is invoked as a SQL Server task in the background (via the SQL Server job scheduler) it throws the errors every time (which is daily) and the results are not produced/it crashes. When I first start up SQL Server Management Studio and run ABC it sometimes throws the error the first time. The second time in this sequence and all subsequent times it does not throw the error. Also, keep in mind that the stored procedure that has been calling MAKE_FUTURE_DATES for 6 months is still quite happy with no errors.
I am looking for suggestions on how to debug this or what to look for. Particularly how can it throw the error sometimes and not others?
The code that you've posted looks fine to me. Is this the complete code?
The only thing that comes to mind is that your "ABC" stored procedure also has a temp table called #TMP_DATES. The temp table in ABC would then also be available in the scope of the called stored procedure.
However, if that were the case, you should get a different error when you called CREATE TABLE #TMP_DATES in the called procedure.
Temp tables have a scope greater than just one procedure.
So you can create a temp table in uspProc1...and if in uspProc1, you call uspProc2, uspProc2 "can see" the temp table you created.
Make sure you provide unique names to your #temp tables.
Below is an example demonstrating the point.
IF EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc001'
)
BEGIN
DROP PROCEDURE [dbo].[uspProc001]
END
GO
CREATE Procedure dbo.uspProc001 (
#Param1 int
)
AS
BEGIN
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
CREATE TABLE #TableOne
(
SurrogateKey int ,
NameOf varchar(12)
)
Insert into #TableOne ( SurrogateKey , NameOf ) select 1001, 'uspProc001'
Select * from #TableOne
EXEC dbo.uspProc002
Select * from #TableOne
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
END
GO
IF EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc002'
)
BEGIN
DROP PROCEDURE [dbo].[uspProc002]
END
GO
CREATE Procedure dbo.uspProc002
AS
BEGIN
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
Insert into #TableOne ( SurrogateKey , NameOf ) select 2001, 'uspProc002'
end
END
GO
exec dbo.uspProc001 0
I have an Informix stored procedure that returns two columns and multiple rows. I can use "EXECUTE FUNCTION curr_sess(2009,'SP')" fine, but how do I get the results into a temp table.
EDIT: We are on version 10.00.HC5
Testing Jonathan Leffler's idea didn't work.
EXECUTE FUNCTION curr_sess(2009,'SP')
works fine. Then I did
CREATE TEMP TABLE t12(yr smallint, sess char(4));
But when I try
INSERT INTO t12 EXECUTE FUNCTION curr_sess(2009,'SP');
It doesn't work, I get a " Illegal SQL statement in SPL routine." error.
The source for curr_sess
begin procedure
DEFINE _yr smallint;
DEFINE _sess char(4);
SELECT
DISTINCT
sess_vw.yr,
sess_vw.sess,
sess_vw.sess_sort
FROM
sess_vw
ORDER BY
sess_vw.sess_sort DESC
INTO temp tmp_sess WITH NO LOG;
SELECT
FIRST 1
tmp_sess.yr,
tmp_sess.sess
FROM
tmp_sess
WHERE
tmp_sess.sess_sort = sess_sort(iYear,sSess)
INTO temp tmp_final WITH NO LOG;
FOREACH cursor1 FOR
SELECT
tmp_final.yr,
tmp_final.sess
INTO
_yr,
_sess
FROM
tmp_final
RETURN _yr, _sess WITH RESUME;
END FOREACH;
DROP TABLE tmp_sess;
DROP TABLE tmp_final;
end procedure
EDIT: sess_sort() does a lookup.
I have tried to rewrite the function as one query. Here is next_sess:
SELECT
FIRST 1
sess_vw.sess_sort
FROM
sess_vw
WHERE
sess_vw.sess_sort > sess_sort(2009,'SP')
ORDER BY
sess_vw.sess_sort ASC
Someone from IBM emailed me and suggested using something like this:
SELECT
*
FROM
TABLE(next_sess(2009,'SP'))
But that still didn't work.
One possibility is a stored procedure. Another (tested on IDS 11.50.FC1), which I wasn't sure would work, is:
CREATE PROCEDURE r12() RETURNING INT, INT;
RETURN 1, 2 WITH RESUME;
RETURN 2, 3 WITH RESUME;
END PROCEDURE;
CREATE TEMP TABLE t12(c1 INT, c2 INT);
INSERT INTO t12 EXECUTE PROCEDURE r12();
The last line is the important one.
Given the observation that the stored procedure cannot be executed as shown just above (because it contains some non-permitted SQL statement), then you need to use stored procedures another way - illustrated by this test code (which works: worked first time, which pleasantly surprised me):
CREATE TEMP TABLE t12(yr smallint, sess char(4));
CREATE PROCEDURE curr_sess(yearnum SMALLINT, sesscode CHAR(2))
RETURNING SMALLINT AS yr, CHAR(4) AS sess;
RETURN yearnum, (sesscode || 'AD') WITH RESUME;
RETURN yearnum, (sesscode || 'BC') WITH RESUME;
END PROCEDURE;
CREATE PROCEDURE r12(yearnum SMALLINT, sesscode CHAR(2))
DEFINE yr SMALLINT;
DEFINE sess CHAR(4);
FOREACH EXECUTE PROCEDURE curr_sess(yearnum, sesscode) INTO yr, sess
INSERT INTO t12 VALUES(yr, sess);
END FOREACH;
END PROCEDURE;
EXECUTE PROCEDURE r12(2009,'SP');
SELECT * from t12;
You could incorporate the creation of the temp table into the stored procedure; you could even arrange to drop a pre-existing table with the same name as the temp table (use exception handling). Given that you're using IDS 10.00, you are stuck with a fixed name for the temp table. It would be possible, though not recommended (by me) to use the dynamic SQL facility in 11.50 to name the temp table at runtime.
Be aware that stored procedures that access temporary tables get reoptimized when reused - the table that is used is not the same as the last time (because it is a temporary) so the query plan isn't all that much help.
That fails possibly because the 'drop table' is not valid statment in a procedure that is used in this context?
http://publib.boulder.ibm.com/infocenter/idshelp/v115/topic/com.ibm.sqls.doc/ids_sqs_1755.htm#ids_sqs_1755