Using a Stored Procedure parameter within the From of another - stored-procedures

I have a Stored Procedure that outputs totals from an eForm table. I want to use this Stored Procedure to pull out data from other eForm tables and so want to replace the eForm table name in the From clause with a parameter. I've read the other questions, but can't find one that helps with using a parameter in From. The code for this Stored Procedure looks like this -
IF OBJECT_ID ('sp_SelectEformMonthlyTotals') IS NOT NULL
DROP PROCEDURE sp_SelectEformMonthlyTotals
GO
CREATE PROCEDURE sp_SelectEformMonthlyTotals #EFORMNAME VARCHAR (200) = ''
AS
CREATE TABLE #TEMP (EFORMNAME VARCHAR (200))
INSERT INTO #TEMP
EXEC sp_UpdateEForm #EFORMNAME
SELECT ....
FROM #EFORMNAME T1 INNER JOIN FLODS_CASE_ENQUIRY_F00 T2 ON T1.EFORM_CASE_ENQUIRY_ID = T2.CASE_ENQUIRY_ID
WHERE T2.CREATED_DT >= '2012-04-02'
GROUP BY MONTH(T2.CREATED_DT), YEAR(T2.CREATED_DT)) T3
ORDER BY YEAR, MONTH_NUMBER
DROP TABLE #TEMP
This is the latest attempt of many and now includes a second Stored Procedure called sp_UpdateEForm -
IF OBJECT_ID ('sp_UpdateEForm') IS NOT NULL
DROP PROCEDURE sp_UpdateEForm
GO
CREATE PROCEDURE sp_UpdateEForm #EFORMNAME VARCHAR (200) = ''
AS
UPDATE FRANCIS
SET eFormName = #EFORMNAME
I created the Francis table to hold the eFormName. I can see that I need to set the value of #EFORMNAME before sp_SelectEformMonthlyTotals can complete, but I just can't seem to find a way of doing this.
Thanks.
Frank

You only need to use a dynamic query for this;
CREATE PROCEDURE sp_SelectEformMonthlyTotals #EFORMNAME VARCHAR (200) = ''
AS
CREATE TABLE #TEMP (EFORMNAME VARCHAR (200))
INSERT INTO #TEMP
EXEC sp_UpdateEForm #EFORMNAME
DECLARE #sSQL AS VARCHAR(2000), #DateCreated as varchar(10)
SET #DateCreated = '2012-04-02'
SET #sSQL = 'SELECT .... '
SET #sSQL = #sSQL + ' FROM ' + #EFORMNAME + ' T1 INNER JOIN FLODS_CASE_ENQUIRY_F00 T2 ON T1.EFORM_CASE_ENQUIRY_ID = T2.CASE_ENQUIRY_ID '
SET #sSQL = #sSQL + ' WHERE T2.CREATED_DT >= '' + #DateCreated + '''
SET #sSQL = #sSQL + ' GROUP BY MONTH(T2.CREATED_DT), YEAR(T2.CREATED_DT)) T3'
SET #sSQL = #sSQL + ' ORDER BY YEAR, MONTH_NUMBER'
exec #sSQL
DROP TABLE #TEMP

Related

Table name as variable in sql server

I am performing stored procedures the input option is as follows:
Declare #table varchar (20)
Set #query = 'Select * from' + #table + 'Where id = 1'
Exec sp_executesql #query
The question is can it be done in some other way without the SQL being handled as varchar?
I was thinking along the lines of something similar to the following:
Declare #varchar varchar(20)
Set #tabla = 'MyTabla'
SELECT * FROM #table

What is the point of using a cursor in a Sybase stored procedure for a simple 1 row UPSERT?

I am looking to re-write a legacy Sybase stored procedure that's 20 years old.
The logic seems pretty simple (an UPSERT of a single row into a table, with the only wrinkle being that unique key for table lookups can be 2 or 3 columns, based on input parameter).
The problem is, the stored procedure accomplishes this by declaring a cursor and using that instead of simply doing an UPSERT (in 2 versions - 2/3 column ones - based on an IF statement).
Is there any reason to use the cursor? Or was this just the original long-gone-developer being too fancy for no good reason?
In case it matters, the details:
Table has key-value pairs, stored for multiple entities. Each key can either be multi-valued or single-valued (which is in a lookup key list table, and is outside the scope of this question). Each record has an active flag:
entity_id int -- foreign key into entity table
unique_id int -- identity column for this table
key varchar(20)
value varchar(255)
active char
comment varchar(20) -- Change control audit purposes.
Stored procedure accepts #entity_id, #key, #value, #active and #comment as input parameters.
Unique key for the table is:
entity_id + key, for keys that are single-valued
entity_id + key + value, for keys that are multiple-valued
The stored procedure does the upsert - if the table already has the row as defined by the unique key, it updates the active flag (and the setting value, for single-valued keys).
If the table does not have the row as defined by unique key, it gets inserted.
The way I would do it would be simple
DECLARE #unique_id int
IF (#key_type="M") -- multi-valued
BEGIN
SELECT #unique_id = unique_id
FROM my_table
WHERE entity_id = #entity_id
AND key = #key
AND value = #value
IF (#unique_id IS NULL) BEGIN
-- INSERT
END
ELSE BEGIN
UPDATE my_table
SET active = #active
,comment = #comment
WHERE entity_id = #entity_id
AND key = #key
AND value = #value
END
END
ELSE -- single-valued
BEGIN
SELECT #unique_id = unique_id
FROM my_table
WHERE entity_id = #entity_id
AND key = #key
IF (#unique_id IS NULL) BEGIN
-- INSERT
END
ELSE BEGIN
UPDATE my_table
SET active = #active
,comment = #comment
,value = #value
WHERE entity_id = #entity_id
AND key = #key
END
END
Instead, the stored procedure does this:
IF (#key_type="M") BEGIN -- multi-valued
DECLARE my_cursor CURSOR
SELECT active FROM my_table
WHERE entity_id = #entity_id
AND key = #key
-- next line is the ONLY difference between single and multiple value cursor
AND value = #value
FOR UPDATE OF value, active, comment
END
ELSE BEGIN -- Single-valued
DECLARE preexisting CURSOR
SELECT active FROM my_table
WHERE entity_id = #entity_id
AND key = #key
FOR UPDATE OF value, active, comment
END
And then does upsert using the cursor:
open my_cursor
DECLARE #cactive CHAR
FETCH my_cursor INTO #cactive
if ( ##sqlstatus = 0 )
UPDATE my_table
SET active = #active
,comment = #comment
,value = #value
WHERE current of my_cursor
ELSE
-- INSERT (no cursor use, same insert I would do)
close my_cursor
deallocate cursor my_cursor

How to create Proc without any variables that compares two tables In SQL Developer?

I skipped Declare statement since it is optional. Got compiler log - error.
CREATE PROCEDURE abc
Begin
WITH xT1 AS
(SELECT Table1.*
FROM Table1
WHERE status_CD ='M' )
SELECT
CASE WHEN Table2.status_cd IS NULL
THEN 'New'
ELSE 'Old'
END AS COMPX
, xT1.*
FROM Table1
LEFT OUTER JOIN table2
ON xT1.t1_ID = table2.t2_ID
;
end;
There is no XT1 table mentioned in your FROM clause. Replace table1 with XT1 in your select statement. below is your modified query
WITH xT1 AS
(SELECT *
FROM test Table1
WHERE no =1 )
SELECT
CASE WHEN Table2.sal IS NULL
THEN 'New'
ELSE 'Old'
END AS COMPX
, xT1.*
FROM xT1
LEFT OUTER JOIN test table2
ON xT1.no = table2.no
;

SQL Error: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=AS;FIRST 100 ROWS ONLY);), DRIVER=3.57.82

The below DB2 stored procedure compiled successfully but getting runtime error SQL Error: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=AS;FIRST 100 ROWS ONLY);), DRIVER=3.57.82
Intention of the below db2 procedure is to delete the records from multiple tables with prepared statements.
CREATE PROCEDURE ALL_DATA_PURGE1(IN v_SCHEMA_NAME VARCHAR(24),IN v_DAYS INTEGER, IN v_COMMIT_COUNT INTEGER)
NOT DETERMINISTIC
LANGUAGE SQL
BEGIN
-- DECLARE Statements
DECLARE SQLCODE INTEGER;
DECLARE v_CRAD_DELETE_QUERY VARCHAR(1024);
DECLARE v_APPDATA_DELETE_QUERY VARCHAR(1024);
DECLARE v_CRAD_DELETE_STATEMENT STATEMENT;
DECLARE v_APPDATA_DELETE_STATEMENT STATEMENT;
SET v_CRAD_DELETE_QUERY = 'DELETE FROM (SELECT 1 FROM ' || v_SCHEMA_NAME || '.CRAD WHERE UNIQUE_ID IN
(SELECT UNIQUE_ID FROM ' || v_SCHEMA_NAME || '.APPDATA WHERE ORIGINATOR_TIMESTAMP < (
SELECT CURRENT TIMESTAMP - '|| v_DAYS ||' DAYS FROM SYSIBM.SYSDUMMY1)
) FETCH FIRST ' || v_COMMIT_COUNT || ' ROWS ONLY) AS DELETE_CRAD_TABLE';
SET v_APPDATA_DELETE_QUERY = 'DELETE FROM (SELECT 1 FROM ' || v_SCHEMA_NAME || '.APPDATA WHERE SOME_TIMESTAMP < (
SELECT CURRENT TIMESTAMP - ' || v_DAYS || ' days FROM sysibm.sysdummy1
) FETCH FIRST ' || v_COMMIT_COUNT || ' ROWS ONLY) AS DELETE_APPDATA_TABLE';
PREPARE v_CRAD_DELETE_STATEMENT FROM v_CRAD_DELETE_QUERY;
PREPARE v_APPDATA_DELETE_STATEMENT FROM v_APPDATA_DELETE_QUERY;
DELETE_LOOP:
LOOP
EXECUTE v_CRAD_DELETE_STATEMENT;
EXECUTE v_APPDATA_DELETE_STATEMENT;
IF SQLCODE = 100 THEN
LEAVE DELETE_LOOP;
END IF;
COMMIT;
END LOOP;
COMMIT;
END
The Stored Procedure compiles because the dynamic SQL statements are not known. At runtime DB2 notices that you are not following its syntax rules. The statements look overly complicated and could be simplified. You don't need to select from sysdummy1 - some simple expressions would do.
Did you test the individual statements before composing the stored procedure?

Declare a table variable without column definitions?

Is there a way, in SQL Server, to declare a table variable without knowing the table definitions?
Exempli gratia:
DECLARE #Results TABLE
INSERT INTO #Results EXEC MyProc #param1 = #myValue
or
DECLARE #Results TABLE
SELECT INTO #Results EXEC MyProc #param1 = #myValue
or
DECLARE #Results TABLE
EXEC MyProc #param1 = #myValue INTO #Results
or
DECLARE #Results TABLE
EXEC INTO #Results MyProc #param1 = #myValue
or
DECLARE #Results TABLE
SELECT * FROM EXEC MyProc #param1 = #myValue INTO #Results
or
DECLARE #Results TABLE
SELECT * INTO #Results FROM EXEC MyProc #param1 = #myValue
or
DECLARE #Results TABLE
SELECT * INTO #Results EXEC MyProc #param1 = #myValue
(you get the idea)
Impossible. Citation from "books online":
==============
Syntax
Note Use DECLARE #local_variable to declare variables of type table.
table_type_definition ::=
TABLE ( { column_definition | table_constraint } [ ,...n ] )
==============
"(", at least one column definition and ")" is syntactically required.
PS: AFAIK insertion into any new table from "exec" results are impossible at all. Only to a table with predefined structre.
You can't do it with table VARIABLES but you can do it with TEMP tables.
-- Drop the table, if it exists
IF OBJECT_ID(N'tempdb.dbo.#tmpMyTable',N'U') IS NOT NULL
DROP TABLE #tmpMyTable
SELECT
ColumnA,
ColumnB
INTO #tmpMyTable
FROM MyTable
-- Then clean up after yourself
DROP TABLE #tmpMyTable

Resources