I'm trying to use a temp table to update a database table in a stored procedure.
My client was throwing an error about an illegal null value, so I tried testing within SSMS and it told me that the name of the temp table was invalid (regardless of what I named it).
If I run the beginning and change the INSERT INTO SERVICE SELECT S.* to simply SELECT S.* and run the code after Declaring and Defining #OldServicesString (so I can leave out the ALTER/CREATE PROCEDURE line) it runs exactly as expected.
Here's the beginning of the SP:
ALTER PROCEDURE [dbo].[app_CreateNewServicesOldFSD] (#OldServicesStr nvarchar(max)) AS
SET NOCOUNT ON
DECLARE #User char(10) = (SELECT TOP 1 CREATED_BY_USER FROM BATCHLOG WHERE BPROCESS_ID = 3 ORDER BY ID DESC);
DECLARE #LastOldService int = (SELECT MAX(ID) FROM SERVICE);
SELECT TOP 0 * INTO #Service FROM SERVICE;
ALTER TABLE #Service
DROP COLUMN RECNUM;
INSERT INTO #Service exec dbo.app_NewServicesOldFSD
;WITH cteOldFSDsToCreate AS (
SELECT JobID.Item JobID, CONVERT(date,ServDate.Item,103) ServDate
FROM dbo.SplitStringToTable(#OldServicesStr,',',2) JobID
INNER JOIN dbo.SplitStringToTable(#OldServicesStr,',',2) ServDate ON JobID.Rw = ServDate.Rw AND JobID.Cl = 0 AND ServDate.Cl = 1
)
INSERT INTO SERVICE SELECT S.*
FROM #Service S
INNER JOIN cteOldFSDsToCreate N ON N.JobID = S.JOB_ID AND N.ServDate = S.DATE
DROP TABLE #Service
A useable and likely #OldServicesStr could be '11428,23/07/2019,11429,23/07/2019,15186,5/10/2019'
To test it in SSMS I opened a new Query and typed in
exec app_CreateNewServicesOldFSD '11428,23/07/2019,11429,23/07/2019,15186,5/10/2019'
And got the following error:
Warning: Null value is eliminated by an aggregate or other SET operation.
Msg 208, Level 16, State 0, Procedure app_CreateNewServicesOldFSD, Line 65 [Batch Start Line 7]
Invalid object name '#Service'.
Completion time: 2020-11-20T20:36:57.1356921+11:00
I know that is not Your case but in the sake of not forget, there is also a limitation using Biztalk WCF-Custom adapter with SQL Bindings and temp tables.
According to this site :
http://thoughtsofmarcus.blogspot.com/2010/11/calling-stored-procedures-from-biztalk.html
You need to SET FMTONLY OFF before creating temp tables and inserting into them and
SET FMTONLY ON before selecting from them as in example from below.
ALTER PROCEDURE [dbo].[FetchTestData]
(#a4 varchar(4))
AS
DECLARE #FmtOnlyIsSet bit = 0
IF (1=0) BEGIN SET #FmtOnlyIsSet = 1 END
IF #FmtOnlyIsSet = 1
SET FMTONLY OFF
SELECT t1, t2, t3 INTO #temp01 FROM Table_1
IF #FmtOnlyIsSet IS NULL
SET FMTONLY ON
SELECT t1, t2, t3 FROM #temp01
RETURN
Related
I have written a stored procedure which executes a stored procedure and the result it gets has to be stored in a local temporary table. The Stored procedure gets created without giving any errors. But when I try to execute stored procedure, it returns the error that the temporary table is invalid object name.
CREATE PROCEDURE .dbo.CalulateETFWeights
-- Add the parameters for the stored procedure here
#CURR_DATE varchar(255),
#ETF_DATE datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--Select max(ETF_DATE) into #ETF_DATE from .dbo.ETF_LIST_V --where ETF_LOAD_DATE = #CURR_DATE
-- Insert statements for procedure here
SELECT TqaSecCode, GlobalSecurity, Cusip
into #tempetftable
from .map.v_get_tqa_security where cusip in (select distinct ETF_CUSIP from .dbo.ETF_LIST_V where ETF_LOAD_DATE = 'Mon Jun 17 14:15:09 BST 2019')
Insert into #tempPriceTable
exec .tqaif.sp_get_ds_price_usd
#sourceTable = '#tempetftable',
#startDate = '20181219',
#endDate = '20181219',
#frequency = 'D'
Insert into .dbo.ETFComponentWeights
Select
C.ETF_CUSIP as W_CAL_CUSIP,
C.STK_IDX as W_CAL_COMP,
C.STK_QUANT as W_CAL_SHARES,
CP.VALUE as W_CAL_PRICE,
(C.STK_QUANT * CP.VALUE_) as W_CAL_MVAL,
(C.STK_QUANT * CP.VALUE_)/SUM(C.STK_QUANT * CP.VALUE) over (partition by C.ETF_CUSIP) as W_CAL_WEIGHT,
#ETF_DATE as W_CAL_DATE
from .dbo.ETF_COMP_V C
inner join (Select E.CUSIP, P.Value_ from #tempPriceTable P inner join #tempetftable E on P.TqaSecCode = E.TqaSecCode) CP
on C.ETF_CUSIP = CP.CUSIP
So the error I get is
Invalid object name '#tempPriceTable'.
I don't understand why is this not working? Can anyone suggest what am I doing wrong here? and why the #tempetftable works fine. But #tempPriceTable here is not working in this scenario?
Syntax:
SELECT TqaSecCode, GlobalSecurity, Cusip
into #tempetftable
creates a new temp table and then inserts data into this new table.
Syntax:
Insert into #tempPriceTable
exec .tqaif.sp_get_ds_price_usd
is a regular "insert into" statement, which adds rows to existing table.
To use this syntax you need to create an empty temp table with correct schema beforehand.
So you need to do something like:
CREATE TABLE #tempPriceTable (your schema)
Insert into #tempPriceTable
exec .tqaif.sp_get_ds_price_usd
I've a Stored procedure which looks like this:
create procedure test as
begin
if exists(
select 1 from sys.columns
where Name = N'Column2'
and Object_ID = Object_ID(Table2')
)
select Column2 from Table2
end
I want to run this procedure on db where Column2 doesn't exist. I don't want to take existence check out of SP. Currently the error is :
Msg 207, Level 16, State 1, Procedure test, Line
39 [Batch Start Line 0] Invalid column name 'Column2'.
Is there any way to do so? Why yes and why not?
and why for instance if you check for existence table and select non-existent table that works?
Use dynamic SQL:
create procedure test as
begin
if exists (select 1
from sys.columns
where Name = N'Column2' and Object_ID = Object_ID('Table2')
)
begin
exec sp_executesql N'select Column2 from Table2';
end;
end;
I created this stored procedure in DB2 using Toad For DB2.
CREATE OR REPLACE PROCEDURE TEST_PROC
BEGIN
DECLARE GLOBAL TEMPORARY TABLE TEMP_TABLE_1(ID INT GENERATED ALWAYS AS IDENTITY,col001 CHAR(36)) NOT LOGGED WITH REPLACE;
DECLARE GLOBAL TEMPORARY TABLE TEMP_TABLE_2(ID INT GENERATED ALWAYS AS IDENTITY,col001 CHAR(36)) NOT LOGGED WITH REPLACE;
DECLARE GLOBAL TEMPORARY TABLE TEMP_TABLE_3(ID INT GENERATED ALWAYS AS IDENTITY,col001 CHAR(36)) NOT LOGGED WITH REPLACE;
INSERT INTO SESSION.TEMP_TABLE_1(col001) VALUES ('TABLE_1_ROW_1');
INSERT INTO SESSION.TEMP_TABLE_1(col001) VALUES ('TABLE_1_ROW_2');
INSERT INTO SESSION.TEMP_TABLE_1(col001) VALUES ('TABLE_1_ROW_3');
INSERT INTO SESSION.TEMP_TABLE_1(col001) VALUES ('TABLE_1_ROW_4');
INSERT INTO SESSION.TEMP_TABLE_2(col001) VALUES ('TABLE_2_ROW_1');
INSERT INTO SESSION.TEMP_TABLE_2(col001) VALUES ('TABLE_2_ROW_2');
INSERT INTO SESSION.TEMP_TABLE_2(col001) VALUES ('TABLE_2_ROW_3');
INSERT INTO SESSION.TEMP_TABLE_3(col001) VALUES ('TABLE_3_ROW_1');
BEGIN
DECLARE temp_cursor CURSOR WITH RETURN TO CLIENT FOR
SELECT tmp.* FROM(
SELECT id, col001 from SESSION.TEMP_TABLE_1
)tmp
Left join SESSION.TEMP_TABLE_2 tmp2 ON tmp2.id = tmp.id
AND EXISTS (SELECT 1 FROM SESSION.TEMP_TABLE_3 t3 WHERE t3.ID = 2);
OPEN temp_cursor;
END;
END;
But executing this stored procedure Call TEST_PROC() generates error.
DB2 Database Error: ERROR [56098] [IBM][DB2/NT64] SQL0727N An error occurred during implicit system action type "5". Information returned for the error includes SQLCODE "-338", SQLSTATE "42972" and message tokens "". SQLSTATE=56098
It does not give any error, if I
Change Left Join to INNER JOIN
Remove this condition AND EXISTS (SELECT 1 FROM SESSION.TEMP_TABLE_3 t3 WHERE t3.ID = 2)
but these two are required.
Any idea what am i doing wrong?
I am new to MS SQL 2014 stored procedure. I have a table as shown below. I want to create a stored procedure.
I design my stored procedure but I feel so difficult that I can’t even start. Can anyone help me how can I do that?
I have to send CardNo, CardPassword and the PosSerialNo to SQL store procedure. In return I need to get customer name, surname and the amount.
SENDING: CardNo, CardPass, PosSerialNo
RECEVING:
If Sending.CardPass = CardPasswordTable.Password
Do the following:
If successful I get: CustomerName, CustomerSurname and Amount
If not I get: “No Data Found”
MY TABLES:
1) CardIssueTable:
Columns:
CardId, CardNo, CustId
2) CustomerTable:
Columns:
CustId, CustName, CustSurname
3) PosTable:
Columns:
PosId, PosSerial, PosLocation
4) PaymentTable:
Columns:
PaymentId, PaymentLoaction, PaymentAmount
5) CardPasswordTable:
Columns:
PassId, Password
Edited:
Here is my Stored Procedure. When I execute I get an error.
Store Procedure:
USE [LTKB_Card]
GO
/****** Object: StoredProcedure [dbo].[CardCustomerControl] Script Date: 2.03.2016 10:03:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*parameters*/
ALTER Procedure [dbo].[CardCustomerControl](
#CardNo varchar(50),
#CardPass varchar(10),
#PosSerialNo varchar(50)
)
AS
BEGIN
DECLARE /*internal of sp*/
#CustName varchar(100),
#CustId int,
#CustSurName varchar(100),
#Amout int,
#PosId int,
#PassId int
SELECT #CustName=CUS.CustomerName, #CustSurName=CUS.CustomerSurname ,#CustId=C.CardCustomer
FROM CardBASIM C
INNER JOIN CUSTOMERS CUS ON C.CardCustomer=CUS.CustomerName
WHERE C.CardNo=#cardNo
SELECT #PassId=PASID FROM CardPASSLIST C WHERE C.CardPassowrd=#CardPass
SELECT #Amout=PT.PaymentAmount
FROM POS P
INNER JOIN PAYMENT PT on P.PosLocation=PT.PAYID
WHERE P.PosSerial=#PosSerialNo
if (#CustId is not null and #PassId is not null and #PosId is not null)
begin
select #CustName CustName, #CustSurName CustSurname , #Amout Amount
end
else
begin
select 'NoDataFound'
end
END
Execute Statement:
USE [LTKB_Card]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[CardCustomerControl]
#CardNo = N'5852354822730001',
#CardPass = N'jSCm6xkBpK',
#PosSerialNo = N'RR-312-001387'
SELECT 'Return Value' = #return_value
GO
Error:
Msg 248, Level 16, State 1, Procedure ElitcardCustomerControl, Line 21
The conversion of the varchar value '5852354822730001' overflowed an
int column.
(1 row(s) affected)
(1 row(s) affected)
And here are the relationship of the tables:
Looking at the data model this line
INNER JOIN CUSTOMERS CUS ON C.CardCustomer=CUS.CustomerName
Is joining a string to an integer. I can't look at the data to see if this is the exact problem but according to your model the join you want is this:
INNER JOIN CUSTOMERS CUS ON C.CardCustomer=CUS.CUSTID
This is a standard relationship -- I've no idea why you felt the Customer's name was the field to join to.
I truly hope you do not store password in plain text, and I don't get all relations between your tables (for example where is relation between postable and paymenttable, between passwordtable and cartable), but I give you an example of SP you needed. Don't forget IT'S JUST EXAMPLE.
CREATE PROCEDURE dbo.spnamegoeshere
#CardNo int,
#CardPass nvarchar(8),
#PosSerialNo nvarchar(8)
AS
BEGIN
--Check if password is Sending.CardPass = CardPasswordTable.Password
IF (SELECT ISNULL(PassId,0) FROM CardPasswordTable WHERE Password = #CardPass) != 0
BEGIN
-- If successful you get: CustomerName,
-- CustomerSurname and Amount
-- not sure of table relations
SELECT ct.CustomerName, ct.CustomerSurname, pat.PaymentAmount
FROM CardIssueTable cit
INNER JOIN CustomerTable ct ON cit.CustId = Ct.CustId
LEFT JOIN PosTable pt ON pt.PosSerial = #PosSerialNo
LEFT JOIN PaymentTable pat ON pt.PosLocation = pat.PaymentLoaction
WHERE CardNo = #CardNo
END
ELSE
BEGIN
--If not you get: “No Data Found”
SELECT 'No Data Found'
END
END
Here's the concept: when a user selects a user list from the frontend treeview and clicks the Save button, the table which contains the mapping for role to users must clear itself of all the users with the role and re insert records with the given role id and userlist.
I am using following stored procedure and function:
Stored procedure:
ALTER PROCEDURE [dbo].[AssignRoleToUser]
#RoleID INT = 0,
#UserID varchar(max) = ''
AS
BEGIN
delete from UserRole
where RoleID = #RoleID
AND UserID IN (SELECT UserID FROM UserRole)
INSERT INTO UserRole(UserID, RoleId)
SELECT id, #RoleID
FROM dbo.CSVToTable(#UserID)
END
Function
CREATE FUNCTION [dbo].[CSVToTable] (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE (id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
But I get this error
Msg 217, Level 16, State 1, Procedure AssignRoleToUser, Line 7
Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32).
Error is exactly saying what went wrong as below, along with the line number.
Msg 217, Level 16, State 1, Procedure AssignRoleToUser, Line 7
Take out the line 7 from your procedure AssignRoleToUser
INSERT INTO UserRole(UserID, RoleId) SELECT id, #RoleID
FROM dbo.CSVToTable(#UserID)
As can be seen, it's calling another function named dbo.CSVToTable. Likewise dbo.CSVToTable may be calling some other procedure\function and that's how the nesting depth has reached to maximum limit. so the error is.
Also, In Line 6 in your procedure AND UserID IN (Select UserID from UserRole) is not needed. which makes it as below
delete from UserRole where RoleID = #RoleID
You can run the below query which will list out all procedure that gets called in chain when running AssignRoleToUser procedure (Query observed from Get All Nested Stored Procedures)
SELECT * FROM
(SELECT NAME AS ProcedureName, SUBSTRING(( SELECT ', ' + OBJDEP.NAME
FROM sysdepends
INNER JOIN sys.objects OBJ ON sysdepends.ID = OBJ.OBJECT_ID
INNER JOIN sys.objects OBJDEP ON sysdepends.DEPID = OBJDEP.OBJECT_ID
WHERE obj.type = 'P'
AND Objdep.type = 'P'
AND sysdepends.id = procs.object_id
ORDER BY OBJ.name
FOR
XML PATH('')
), 2, 8000) AS NestedProcedures
FROM sys.procedures procs )InnerTab
WHERE NestedProcedures IS NOT NULL
AND NAME = 'AssignRoleToUser'
The error says that you have a call to a procedure, function, or trigger which calls another one which calls another one, etc etc, until the call is 32 calls deep. At this point it's giving and saying 'too much!'.
Do you have any triggers on the UserRole table? Will they call other things? If so, what will they do? And so on...