I don't quite understand how MariaDB signals work.
I have a stored procedure that takes a string as input. I am testing that string for valid characters. If invalid characters are found then I want to send a signal that the error was invalid. Will a stored procedure immediately exit if a SIGNAL SQLSTATE '......' SET MESAGE_TEXT='......' is raised? Or will it complete the procedure before issuing the signal?
When just using IF...THEN statements it does not seem to work.
CREATE PROCEDURE `testP`()
BEGIN
IF testStringSecurity('he;llo world') != 0 THEN
SELECT 'INVALID CHARACTERS';
END IF;
SELECT 'GOOD TO GO';
END;
Always returns GOOD TO GO. It seems that you must wrap in IF ... THEN ... ELSE like so to get a valid case. Though setting a signal is different.
CREATE PROCEDURE `testP`()
BEGIN
IF testStringSecurity('he;llo') != 0 THEN
SELECT 'INVALID CHARACTERS';
ELSE
SELECT 'GOOD TO GO';
END IF;
END
Using a SIGNAL does seem to interrupt execution immediately.
CREATE PROCEDURE `testP`()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE,
#errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
SET #full_error = CONCAT("ERROR ", #errno, " (", #sqlstate, "): ", #text);
SELECT #full_error;
END;
DECLARE EXIT HANDLER FOR NOT FOUND
BEGIN
SELECT CONCAT('ERROR: ',#str,' RETRUNED NOT FOUND EXCEPTION.');
END;
IF testStringSecurity('he;llo') != 0 THEN
SIGNAL SQLSTATE '42000'
SET MESSAGE_TEXT = 'ERROR: Invalid string';
END IF;
SELECT 'GOOD TO GO';
END
Returns 'ERROR 1644 (42000): ERROR: Invalid string'
Related
So i created a procedure with one input parameter and it compiles successfully but when i call it, it says "PL/SQL procedure successfully completed" but no values are printed
I have tried different ways to execute procedures and none of them have worked.
This is my code below:
CREATE OR REPLACE PROCEDURE vendorInfo (vendorID in NUMBER) AS
V_NAME VENDORS.VENDOR_NAME%TYPE;
V_CITY VENDORS.VENDOR_CITY%TYPE;
I_ID INVOICES.INVOICE_ID%TYPE;
I_TOTAL INVOICES.INVOICE_TOTAL%TYPE;
I_P_TOTAL INVOICES.PAYMENT_TOTAL%TYPE;
I_C_TOTAL INVOICES.CREDIT_TOTAL%TYPE;
STATUS VARCHAR2(15);
CURSOR vendor_cursor IS
SELECT INVOICE_ID,INVOICE_TOTAL,PAYMENT_TOTAL,CREDIT_TOTAL FROM
INVOICES
WHERE VENDOR_ID = vendorID;
BEGIN
SELECT VENDOR_NAME,VENDOR_CITY INTO V_NAME,V_CITY
FROM VENDORS
WHERE VENDOR_ID = vendorID;
DBMS_OUTPUT.PUT_LINE('VENDOR NAME:'|| V_NAME || ' VENDOR
CITY:'|| V_CITY);
OPEN vendor_cursor;
LOOP
FETCH vendor_cursor INTO I_ID,I_TOTAL,I_P_TOTAL,I_C_TOTAL;
EXIT WHEN vendor_cursor%NOTFOUND;
IF (I_TOTAL - I_P_TOTAL - I_C_TOTAL) = 0 THEN
STATUS := 'PAID';
ELSE
STATUS := 'NOT_PAID';
END IF;
DBMS_OUTPUT.PUT_LINE('INVOICE ID:' || I_ID ||' INVOICE
TOTAL:'|| I_TOTAL || ' STATUS:' || STATUS);
END LOOP;
CLOSE vendor_cursor;
END vendorInfo;
/
begin
vendorInfo(95);
end;
/
You have to enable output.
If you're running this piece of code in SQL*Plus or SQL Developer, you'd - before calling the procedure - run
set serveroutput on --> this
begin
vendorInfo(95);
end;
/
If you're using some other GUI (you tagged the question with PL/SQL Developer tag - I don't use it so I can't tell for sure), then you'll have to enable it somehow. In TOAD, for example, click the button in "DBMS Output" pane:
I want the procedure to fail in case of any conditions been met.
Is there a way to conditionally exit the Snowflake stored procedure with error.
RAISE could be used.
Raises an exception.
-- Stored Procedure - Snowflake Scripting
CREATE OR REPLACE PROCEDURE test_proc(ARG INT)
RETURNS INT
LANGUAGE SQL
AS
DECLARE
my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
IF (ARG = 2) THEN
RAISE my_exception;
END IF;
RETURN ARG;
END;
Test:
CALL test_proc(1);
-- 1
CALL test_proc(2);
-- -20002 (P0001): Uncaught exception of type 'MY_EXCEPTION' on line 5 at position 8:
-- Raised MY_EXCEPTION.
I am trying to write a procedure to verify if there was any issues during import so I can raise an error. So I wrote the following block of SQL inside of my stored procedure. But I always get a null value for all the fetched values(actualRowCount, skippedRowCount, importedRowCount, updatedRows, rejectedRows, committedRows) except for the msgs.
I am unable to find why would I get values only for the msgs but not for others. They all should have at least 0 as a value. Please Assume all necessary variables declared in the procedure already.
I get a DB2 SQL-Error: -438 when I do a RAISE_APPLICATION_ERROR outside of the If block for testing purpose and get a null error when I try to print using Put_LINE
Begin Atomic
CALL SYSPROC.ADMIN_CMD( 'IMPORT FROM /tmp/city.ixf OF ixf MESSAGES ON SERVER INSERT INTO city');
ASSOCIATE RESULT SET LOCATORS(resultSet) WITH PROCEDURE SYSPROC.ADMIN_CMD;
ALLOCATE C1 CURSOR FOR RESULT SET resultSet;
FETCH C1 INTO actualRowCount, skippedRowCount , importedRowCount, updatedRows, rejectedRows, committedRows, msgs;
IF actualRowCount <> importedRowCount THEN
CALL RAISE_APPLICATION_ERROR(-20040, 'import fail:' || msgs);
END IF;
Close C1;
End;
Sample message handler for IMPORT with ADMIN_CMD:
--#SET TERMINATOR #
SET SERVEROUTPUT ON#
BEGIN
DECLARE actualRowCount, skippedRowCount, importedRowCount, updatedRows, rejectedRows, committedRows BIGINT;
DECLARE msg_sel, msg_del VARCHAR(128);
DECLARE SQLSTATE CHAR(5);
DECLARE V_SQLCODE VARCHAR(10);
DECLARE V_MSG VARCHAR(1024);
DECLARE resultSet RESULT_SET_LOCATOR VARYING;
DECLARE C2 CURSOR FOR S2;
CALL SYSPROC.ADMIN_CMD('IMPORT FROM /tmp/city.ixf OF ixf MESSAGES ON SERVER INSERT INTO city');
ASSOCIATE RESULT SET LOCATORS (resultSet) WITH PROCEDURE SYSPROC.ADMIN_CMD;
ALLOCATE C1 CURSOR FOR RESULT SET resultSet;
FETCH C1 INTO actualRowCount, skippedRowCount , importedRowCount, updatedRows, rejectedRows, committedRows, msg_sel, msg_del;
CLOSE C1;
IF COALESCE(msg_sel, '') <> '' THEN
CALL DBMS_OUTPUT.PUT_LINE('msg_sel: ' || msg_sel);
PREPARE S2 FROM msg_sel;
OPEN C2;
L2: LOOP
FETCH C2 INTO V_SQLCODE, V_MSG;
IF SQLSTATE = '02000' THEN LEAVE L2; END IF;
CALL DBMS_OUTPUT.PUT_LINE(V_SQLCODE || ': ' || V_MSG);
END LOOP L2;
CLOSE C2;
END IF;
CALL DBMS_OUTPUT.PUT_LINE('msg_del: ' || msg_del);
EXECUTE IMMEDIATE msg_del;
END#
The requirement is to get the log of all the DML statements executed inside a Stored Procedure in teradata. This Stored procedure is being called inside a shell script using BTEQ. The ask is to capture the log of all activities performed inside the shell into a log file in unix. If any error occurs, that also needs to be captured.
The Stored Procedure contains 20 Merge SQLs and i want to see how many rows got affected and how long each statement took. I tried calling the individual merges through BTEQ(instead of calling it in a Stored Procedure), but there is significant time gain if its called inside an SP. Right now, all i can see is that the Stored procedure has been completed successfully.
replace procedure SP_Test()
BEGIN
MERGE INTO T1 using T2 on T1.C1 = T2.C1
WHEN NOT MATCHED THEN INSERT (C1,C2,C3) VALUES (T2.C1,T2.C2,T3.C3)
WHEN MATCHED
THEN UPDATE
SET
C1 = CASE statement 1
C2 = CASE statement 2
c3 = CASE statement 3 ;
END;
inside the BTEQ block of test.sh shell script,
bteq << EOF >>LOgFILE.txt 2>&1
.LOGON source/user,password;
.COMPILE FILE = sp_merge.txt;
.IF ERRORCODE <> 0 THEN .GOTO QUITNOTOK
call SP_Test();
.IF ERRORCODE <> 0 THEN .GOTO QUITNOTOK
.LABEL QUITOK
.LOGOFF
.QUIT 0
.LABEL QUITNOTOK
.QUIT 2
EOF
Log File currently
**** Procedure has been executed.
**** Total elapsed time was 2 minutes and 47 seconds.
Expected Output
**** Merge completed. 5641191 rows affected.
5641191 rows inserted, no rows updated, no rows deleted.
**** Total elapsed time was 2 minutes and 45 seconds.
You can do one thing.
Write another procedure and keep an insert statement like this below :
REPLACE PROCEDURE <DB_USER>. log_process_run_message ( IN in_n_process_run_id DECIMAL(18,0) ,
IN in_v_process_name VARCHAR(30) ,
IN in_v_message_txt VARCHAR(50000) ,
IN in_d_message_ts TIMESTAMP(6)
)
BEGIN
BT; -- Begin Transaction
INSERT INTO <SCHEMA_NAME>.cop_process_run_message_op
(
process_name ,
message_txt ,
message_ts
)
VALUES (
in_v_process_name ,
in_v_message_txt ,
in_d_message_ts
);
ET; -- End Transaction
END;
In your main procedure include an exit handler;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET lv_sql_state = SQLSTATE;
SET ln_sql_code = SQLCODE;
SET out_status = 'FAILED';
ROLLBACK;
SET lv_my_mesg = 'Error in : ' || lv_my_mesg || ' - SQLSTATE: ' || lv_sql_state || ', SQLCODE: ' || CAST(ln_sql_code AS CHAR);
CALL <DB_USER>.log_process_run_message (ln_run_id,lv_err_component,lv_my_mesg,CURRENT_TIMESTAMP(6));
END;
Also define the below variable in your main procedure
SET lv_err_component='ur proc name'
Now call this procedure inside your main procedure after every merge statement:
SET lv_my_mesg ='Merge 1 completed '||CAST(CURRENT_TIMESTAMP(0) AS CHAR(19));
CALL <DB_USER>.log_process_run_message (lv_err_component,lv_my_mesg,CURRENT_TIMESTAMP(6));
What this will do is, it will insert a record after successful execution of your merge statements and in case there is an error it will
execute the call statement in the exit handler and will document your error message as well in case there is any.Let me know if this helps.
In SQL Server you can write SQL to check if a table exists. How can I do that for ADS?
I have a need to write some Delphi code to say if table exists do this else this...
The system procedure sp_GetTables can tell you what tables exist in the directory that you connected to:
EXECUTE PROCEDURE sp_GetTables( NULL, NULL, NULL, 'TABLE' )
A non-SQL solution would be to use the AdsCheckExistence API.
I'm not ADS user, so I can't answer in detail.
See http://devzone.advantagedatabase.com/dz/webhelp/Advantage10.1/index.html
The're is system.tables view with information about tables.
I suppose you also can write SQL query to check a table.
I like Peter's answer, but depending on what it is you need to do, you might be looking for a TRY, CATCH, FINALLY statement.
TRY
// Try to do something with the table
select top 1 'file exists' from "non_existing_table";
CATCH ADS_SCRIPT_EXCEPTION
// If a "7041 - File does not exist" error ocurrs
IF __errcode = 7041 THEN
// Do something else
select 'file does not exist' from system.iota;
ELSE
// re-raise the other exception
RAISE;
END IF;
END TRY;
Delphi code:
function TableExists(AConnection: TADOConnection; const TableName: string): boolean;
var
R: _Recordset;
begin
if AConnection.Connected then
try
R := AConnection.Execute('Select case when OBJECT_ID(''' + TableName + ''',''U'') > 0 then 1 else 0 end as [Result]', cmdText, []);
if R.RecordCount > 0 then
Result := (R.Fields.Items['Result'].Value = 1);
except on E:exception do Result := false;
end;
this simple function use existing TADOConnection
end;