db2 Stored Procedure Merge Error - stored-procedures

I am trying to create a stored procedure that will run a merge from a staging table to the master table, however, I am getting this error when I try to create:
DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=END-OF-STATEMENT;.LAST_CHANGED_DATE
);<psm_semicolon>, DRIVER=3.69.24 [SQL State=42601, DB Errorcode=-104]
Any help would be appreciated
CREATE PROCEDURE sp_UpdateM25
LANGUAGE SQL
BEGIN
MERGE INTO MEDILOAD.M25 M25
USING ( SELECT NDC_UPC_HR1,
ID_NUM_FORMAT,
REC_CODE,
TRAN_CODE,
OVERLOADED_AREA,
LAST_CHANGED_DATE
FROM MEDILOAD.M25_STAGE) M25_STAGE
on (M25.NDC_UPC_HR1 = M25_STAGE.NDC_UPC_HR1 and M25.REC_CODE = M25_STAGE.REC_CODE)
WHEN matched then
update set
M25.NDC_UPC_HR1 = M25_STAGE.NDC_UPC_HR1,
M25.ID_NUM_FORMAT = M25_STAGE.ID_NUM_FORMAT,
M25.REC_CODE = M25_STAGE.REC_CODE,
M25.TRAN_CODE = M25_STAGE.TRAN_CODE,
M25.OVERLOADED_AREA = M25_STAGE.OVERLOADED_AREA,
M25.LAST_CHANGED_DATE = M25_STAGE.LAST_CHANGED_DATE
WHEN NOT MATCHED then
INSERT
(
M25.NDC_UPC_HR1,
M25.ID_NUM_FORMAT,
M25.REC_CODE,
M25.TRAN_CODE,
M25.OVERLOADED_AREA,
M25.LAST_CHANGED_DATE
)
VALUES
(
M25_STAGE.NDC_UPC_HR1,
M25_STAGE.ID_NUM_FORMAT,
M25_STAGE.REC_CODE,
M25_STAGE.TRAN_CODE,
M25_STAGE.OVERLOADED_AREA,
M25_STAGE.LAST_CHANGED_DATE
);
END
#

Related

Is if...exists supported in Snowflake stored procedures?

I have written a stored procedure which will be called from python. The stored procedure needs to insert the variant data into my table if the id doesn't exist or update the existing variant data where there is a match for the id. The id will be passed the way the variant data is, but for now I am just trying to get it working with a hardcoded id. The stored procedure gets called successfully from python, but then nothing gets inserted or updated in the stored procedure and the stored procedure doesn't give me an error. I am not sure if I am doing something wrong or the...
if exists (select * from my_database_table where my_variant_data:id::varchar = '123456')
... part is being ignored because it isn't supported. I haven't been able to find anything in the documentation to prove or disprove this. Does anyone know?
create or replace procedure my_stored_procedure("variant_data" variant)
returns string
language javascript
strict
execute as owner
as
$$
var insert_update_query = `
if exists (select * from my_database_table where my_variant_data:id::varchar = '123456')
begin
update my_database_table SET my_variant_data = parse_json(:1)) WHERE my_variant_data:id::varchar = '123456'
end
else
begin
insert into my_database_table(my_variant_data) select (parse_json(:1));
end
`
var result = "";
try {
var sql_insert_update_query = snowflake.createStatement({
sqlText: insert_update_query
});
var insert_update_query_result = sql_insert_update_query.execute();
result += "\n Query succeeded";
} catch (err) {
result += "\n Query failed failed: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\n Stack Trace:\n" + err.stackTraceTxt;
}
return result;
$$
;
I have tested the insert and update parts of the query in the stored procedure individually and they work fine.
Insert - works as expected.
create or replace procedure my_stored_procedure("variant_data" variant)
returns string
language javascript
strict
execute as owner
as
$$
var sql_command = "insert into my_database_table(my_variant_data) select (parse_json(:1));";
var sql = snowflake.createStatement( {sqlText: sql_command, binds:[JSON.stringify(variant_data)]});
var resultSet = sql.execute();
return sql_command;
$$
;
Update - works as expected.
create or replace procedure my_stored_procedure("variant_data" variant)
returns string
language javascript
strict
execute as owner
as
$$
var sql_command = "UPDATE my_database_table SET my_variant_data = parse_json(:1)) WHERE my_variant_data:id::varchar = '123456'";
var sql = snowflake.createStatement( {sqlText: sql_command, binds:[JSON.stringify(variant_data)]});
var resultSet = sql.execute();
$$
;
Given the CODE executed needs to be valid runs on the console SQL, which this if is not, and it is fundamentally a MERGE command I would suggest flipping the code into a MERGE:
MERGE INTO my_database_table USING my_database_table
ON my_variant_data:id::varchar = '123456'
WHEN MATCHED THEN UPDATE SET my_variant_data = parse_json(:1))
WHEN NOT MATCHED THEN INSERT (my_variant_data) VALUES (parse_json(:1));
otherwise if you are want it in SP space, then I would be inclinded to break the code into a SELECT x INTO varaible FROM blar pattern and then have the IF be in SP and pick between the two blocks of SQL to run. But given it's just a merge, I would again still, do a merge.

Error -206 creating Interbase stored procedure

I am attempting to create a stored procedure using an IBConsole interactive SQL window. The intent of the procedure is to gather data from two tables, do some processing on that data, insert rows containing that data into a working table, then return the rows from the working table as the stored procedure result. The stored procedure:
SET TERM ^;
CREATE PROCEDURE BIBLIO_SUBJECT
RETURNS (ID INTEGER, SUBJECT VARCHAR(200))
AS
DECLARE VARIABLE CUR_SUBJECT VARCHAR(200);
DECLARE VARIABLE SUBJECT_LIST VARCHAR(500);
DECLARE VARIABLE BIBLIOID INTEGER;
DECLARE VARIABLE NEXTPOS INTEGER;
BEGIN
DELETE FROM TSUBJECTS;
FOR SELECT BIBLIO.ID, BIBLIO.SUBJECTS
FROM BIBLIO
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :SUBJECT_LIST
DO
BEGIN
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
NEXTPOS = LOCATE(";", SUBJECT_LIST);
WHILE (:NEXTPOS > 1) DO
BEGIN
CUR_SUBJECT = SUBSTR(:SUBJECT_LIST, 1, NEXTPOS - 1);
SUBJECT_LIST = SUBSTR(:SUBJECT_LIST, NEXTPOS + 1, STRLEN(SUBJECT_LIST));
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
NEXTPOS = LOCATE(";", SUBJECT_LIST);
END
END
FOR SELECT BIBLIO_BEAST.BIBLIO_ID, BEAST.BEAST_NAME
FROM BIBLIO_BEAST
INNER JOIN BEAST ON (BEAST.ID = BIBLIO_BEAST.BEAST_ID)
INNER JOIN BIBLIO ON (BIBLIO.ID = BIBLIO_BEAST.BIBLIO_ID)
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :CUR_SUBJECT
DO
BEGIN
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
END
FOR SELECT ID, SUBJECT
FROM TSUBJECTS
INTO :ID, :SUBJECT
DO
SUSPEND;
END^
SET TERM ;^
When I execute the above code in IBConsole I get the error:
Error at line 2
Dynamic SQL Error
SQL error code = -206
Column unknown
SQL - CREATE PROCEDURE BIBLIO_SUBJECT
RETURNS (ID INTEGER, SUBJECT VARCHAR(200))
AS
DECLARE VARIABLE CUR_SUBJECT VARCHAR(200);
DECLARE VARIABLE SUBJECT_LIST VARCHAR(500);
DECLARE VARIABLE BIBLIOID INTEGER;
DECLARE VARIABLE NEXTPOS INTEGER;
BEGIN
DELETE FROM TSUBJECTS;
FOR SELECT BIBLIO.ID, BIBLIO.SUBJECTS
FROM BIBLIO
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :SUBJECT_LIST
DO
BEGIN
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
NEXTPOS = LOCATE(";", SUBJECT_LIST);
WHILE (:NEXTPOS > 1) DO
BEGIN
CUR_SUBJECT = SUBSTR(:SUBJECT_LIST, 1, NEXTPOS - 1);
SUBJECT_LIST = SUBSTR(:SUBJECT_LIST, NEXTPOS + 1, STRLEN(SUBJECT_LIST));
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
NEXTPOS = LOCATE(";", SUBJECT_LIST);
END
END
FOR SELECT BIBLIO_BEAST.BIBLIO_ID, BEAST.BEAST_NAME
FROM BIBLIO_BEAST
INNER JOIN BEAST ON (BEAST.ID = BIBLIO_BEAST.BEAST_ID)
INNER JOIN BIBLIO ON (BIBLIO.ID = BIBLIO_BEAST.BIBLIO_ID)
WHERE BIBLIO.PUBLISH = TRUE
INTO :BIBLIOID, :CUR_SUBJECT
DO
BEGIN
INSERT INTO TSUBJECTS (SUBJECT, ID) VALUES(:CUR_SUBJECT, :BIBLIOID);
END
FOR SELECT ID, SUBJECT
FROM TSUBJECTS
INTO :ID, :SUBJECT
DO
SUSPEND;
END
It doesn't say which column is "unknown", and line 2 is (apparently) the RETURNS clause of the CREATE PROCEDURE. Not at all helpful.
Each of the SQL statements in the stored procedure (3 SELECTs, a DELETE, 2 INSERTs) work without error if executed separately in an Interactive SQL window, so all of their columns are "known". BIBLIO_SUBJECT is not the name of an existing stored procedure, nor is it the name of an existing table, or anything else in the database.
This has me baffled. Online searches provide no answer. So I am hoping the clever Stack Overflow people can help me get this working.
David
Well, I figured it out. It was the statement:
SUBJECT_LIST = BIBLIO.SUBJECTS + ';';
The SUBJECT_LIST variable is already used in the preceding select. A silly mistake, but I am old.
Not that it matters since the Interbase UDF functions Locate() and Substr() can only handle 80 character strings, which makes them really useless to me... and probably useless to most.

Dynamic Creation of External Tables in Synapse

I have a json string which is the result of Get Metadata activity in data factory in the following format: {"structure": [{"name": "Id","type": "String"},{"name": "IsDeleted","type": "Boolean"},{"name": "RowVersion","type": "Byte[]"}, {"name": "ModelId","type": "String"}]
This json is showing the schema of parquet file. I pass this json along with the parquet filename and uctnow() to a stored procedure to create a table of schema for that file with the following code
CREATE OR ALTER PROCEDURE [CreateExternalTables] (
#schema NVARCHAR (MAX), #tableName NVARCHAR(MAX), #ExecTime NVARCHAR(MAX)
) AS
BEGIN
IF OBJECT_ID('tempdb..#tables_to_create', 'U') IS NOT NULL
DROP TABLE #tables_to_create
CREATE TABLE #tables_to_create (
tableName NVARCHAR (MAX),
fieldOrder NVARCHAR (MAX),
fieldName NVARCHAR (MAX),
fieldType NVARCHAR (MAX),
translatedType NVARCHAR (MAX),
executeTime NVARCHAR (MAX)
)
BEGIN
WITH Fields (fieldOrder, fieldName, fieldType) AS (
SELECT
[key] AS fieldOrder,
JSON_VALUE([value], '$.name') AS fieldName,
JSON_VALUE([value], '$.type') AS fieldType
FROM
OPENJSON(#schema)
)
INSERT INTO
#tables_to_create(
tableName,
fieldOrder,
fieldName,
fieldType,
translatedType,
executeTime
)
SELECT
#tableName,
fieldOrder,
fieldName,
fieldType,
CASE
WHEN fieldType = 'Single' THEN 'real'
WHEN fieldType = 'Boolean' THEN 'bit'
WHEN fieldType = 'Double' THEN 'float'
WHEN fieldType = 'Int64' THEN 'bigint'
ELSE NULL
END AS translatedType,
#ExecTime
FROM
Fields
END
END;
The overall setup is like below:
But I receive the following error which I'm not sure why:
What I would like to do is to create this temo table in stored procedure in order to create external tables in a automatic way.
To be precise I'm following this link to do it:
create-external-dataset
Any help is highly appreciated.
UPDATE
After solving the first problem with #wBob 's help I follow the rest of the link to create the external tables with the following which I inserted into my stored procedure:
FROM
Fields
END
Declare #sqlCommand nvarchar(max);
Declare #folderPath nvarchar(max);
SET
#sqlCommand = 'IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[' + #tableName + ']'') AND type in (N''U''))
CREATE EXTERNAL TABLE [dbo].[' + #tableName + '] ('
WHILE((SELECT COUNT(*) FROM #tables_to_create) > 0)
BEGIN
DECLARE #key int
SELECT
#key = MIN(fieldOrder)
FROM
#tables_to_create
WHERE
executeTime = #ExecTime
DECLARE #fieldName VARCHAR(50)
DECLARE #translatedType VARCHAR(50)
SELECT
#fieldName = fieldName,
#translatedType = translatedType
FROM
#tables_to_create
WHERE
fieldOrder = #key
AND executeTime = #ExecTime
SET
#sqlCommand = #sqlCommand + '
[' + #fieldName + '] [' + #translatedType + '] NULL'
DELETE FROM
#tables_to_create
WHERE
fieldOrder = #key
AND executeTime = #ExecTime
IF((SELECT COUNT(*) FROM #tables_to_create WHERE executeTime = #ExecTime) > 0)
SET
#sqlCommand = #sqlCommand + ', '
END
SET
#sqlCommand = #sqlCommand + '
)
WITH
(
LOCATION = ''/' + /main/json/ + ''',
DATA_SOURCE = DataLakeStaged,
FILE_FORMAT = StagedParquet
)'
EXEC(#sqlCommand)
END;
However I receive the following error:
As per the error message, queries are not supported in the conditions of WHILE statement in Azure Synapse Analytics. Dedicated SQL pools are MPP systems that have some slight differences from box-product SQL Server and Azure SQL DB and more generally, loops are a pattern that don't translate that well. You should consider creating a stored procedure that does not loop and leave any looping required to the For Each activity in Azure Data Factory (ADF) / Synapse Pipelines which can loop in parallel.
If you do require a loop, there are multiple examples of doing loops in dedicated SQL pools online, but there is a good example in the official documentation, reproduced here in the event the link moves:
-- First, create a temporary table containing a unique row number used to identify the individual statements:
CREATE TABLE #tbl
WITH
( DISTRIBUTION = ROUND_ROBIN
)
AS
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Sequence
, [name]
, 'UPDATE STATISTICS '+QUOTENAME([name]) AS sql_code
FROM sys.tables
;
-- Second, initialize the variables required to perform the loop:
DECLARE #nbr_statements INT = (SELECT COUNT(*) FROM #tbl)
, #i INT = 1
;
-- Now loop over statements executing them one at a time:
WHILE #i <= #nbr_statements
BEGIN
DECLARE #sql_code NVARCHAR(4000) = (SELECT sql_code FROM #tbl WHERE Sequence = #i);
EXEC sp_executesql #sql_code;
SET #i +=1;
END

Procedure runs,but doesn't do anything

I have a little problem with running a certain procedure in MariaDB.
The funny thing is that when i run the procedure,it doesn't show any errors,but unfortunately it doesn't do anything.
And I can't simply find what's wrong.
Guys please help.Thx
Query:
CREATE DEFINER=`root`#`127.0.0.1` PROCEDURE `p_tun_removal`(IN `GeoTerID` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
BEGIN
DECLARE #done INT DEFAULT FALSE;
DECLARE #CurrentVersion INT;
DECLARE #CorrectVersion INT;
DECLARE #BeginVersion INT;
DECLARE cur1
CURSOR FOR
SELECT Distinct(Version)
FROM geo_patch
WHERE TerID = GeoTerID AND Version >= BeginVersion;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
declare exit handler for sqlexception
begin
rollback;
resignal;
end;
CREATE Temporary TABLE `tunnel_temp` (
`ID` INT NOT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
insert into tunnel_temp ( ID ) (
SELECT ID from geo_patch
WHERE Version in ( select Version from geo_patch where Substance = 0 ) and TerID = GeoTerID
);
SET #BeginVersion = ( SELECT Version from geo_patch where ID = ( SELECT ID from tunnel_temp limit 1 ) ) - 1 ;
SET #CorrectVersion = #BeginVersion;
IF (#CorrectVersion < 2) THEN
SET #CorrectVersion = 2;
END IF;
START TRANSACTION;
DELETE FROM geo_patch where ID in ( Select ID from tunnel_temp );
open cur1;
version_loop: LOOP
FETCH cur1 into #CurrentVersion;
IF done THEN
LEAVE version_loop;
END IF;
UPDATE geo_patch SET Version = #CorrectVersion WHERE Version = #CurrentVersion;
SET CorrectVersion = CorrectVersion + 1;
END LOOP;
close cur1;
COMMIT;
UPDATE terrain_blocks SET GeoVersion = ( select Version from geo_patch where TerID = GeoTerID order by Version desc limit 1 ) WHERE ID = GeoTerID;
drop temporary table if exists tunnel_temp;
END
Don't use the construct IN ( SELECT ... ), use a JOIN instead.
Try to avoid cursors by doing the entire operation in a single statement.

VB6 Call stored procedure with parameters

As the headling says I want to call a stored procedure with parameters.
Below is the VB6-function that
Private Sub TestProcedur()
Dim strSql As String
Dim CPw As rdoQuery
strSql$ = "? = {call Insert_Student(?) }"
Set CPw = gRdoConn.CreateQuery("InsertStudent", strSql)
CPw.rdoParameters(0).Direction = rdParamReturnValue
CPw(1) = "FRANK"
Set mrsR = CPw.OpenResultset()
End Sub
The stored procedure below
CREATE PROCEDURE Insert_Student
#Name VARCHAR(50)
AS
BEGIN
INSERT INTO dbo.Student (Name)
VALUES (#Name)
END
GO
I'm getting a problem when running the function. A ERROR messsage occurs when running the line "CPw.rdoParameters(0).Direction = rdParamReturnValue" that says: Not valid description index"
This page on MSDN should explain it nicely:
http://msdn.microsoft.com/en-us/library/aa240826%28v=VS.60%29.aspx

Resources