Netezza Stored procedure DB_NAME as an argument - sql

HI everyone I wrote a kind of a simple procedure in Aginity(Netezza). The stored procedure basically has to load data from one db.table1 to db2.table2. Simple right? Then then the procedure - procedure 1 takes in an argument, which is the name of the database(db).
This is the error message I get whenever I try to run my procedure:
/*
ERROR [HY000] ERROR: syntax error, unexpected VARIABLE, expecting BEGIN at or near "db_arg"
*/
The procedure looks like something like this:
CREATE OR REPLACE PROCEDURE LOAD_data_proc(CHARACTER VARYING(15))
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
db_arg CHARACTER VARYING(15);
/* if I remove above declaration I get the following error message: ERROR [HY000] ERROR: ResolveCatalog: error retrieving database 'STG_DB_NAME' */
db_arg ALIAS FOR $1;
/* and bunch of other arguments and declarations */
BEGIN
/* logic here if then else statements */
END;
END_PROC;
Did anyone encounter this problem before?

It's not 100% clear from your description what the actual NZPLSQL code is, but I can reproduce your first error using:
CREATE OR REPLACE PROCEDURE LOAD_DATA_PROC(CHARACTER VARYING(15))
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
db_arg CHARACTER VARYING(15);
db_arg alias for $1;
BEGIN
db_arg := 'SYSTEM';
RAISE NOTICE '%', db_arg;
RETURN 0;
END;
END_PROC;
Note there is a double declaration of the same variable name in the DECLARE block. This is not allowed, and this causes:
ERROR [HY000] ERROR: syntax error, unexpected VARIABLE, expecting BEGIN at or near "db_arg"
Removing one of the declarations will allow the procedure to complete.
IBM docs on NZPLSQL regarding parameter passing to stored procedures is available here: https://www.ibm.com/support/knowledgecenter/SSULQD_7.2.0/com.ibm.nz.sproc.doc/c_sproc_parameter_passing.html
and here:
https://www.ibm.com/support/knowledgecenter/SSULQD_7.2.0/com.ibm.nz.sproc.doc/c_sproc_arg_list.html
As for:
ERROR [HY000] ERROR: ResolveCatalog: error retrieving database 'STG_DB_NAME'
This occurs when I attempt to call a non-existent stored procedure, in a non-existent schema of a non-existent database such as:
CREATE OR REPLACE PROCEDURE LOAD_DATA_PROC(CHARACTER VARYING(15))
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
db_arg alias for $1;
BEGIN
CALL UNKNOWNDB.UNKNOWN_SCHEMA.UNKNOWN_STORED_PROC(1234,5678,7890,123456,1234567);
END;
END_PROC;
which gives me:
ERROR [HY000] ERROR: ResolveCatalog: error retrieving database 'UNKNOWNDB'
Hopefully this helps to explain the errors and how to avoid them.

ok I figured it out... you can pass db_names as arguments to the netezza stored procedure but every time you use the argument inside the procedure, you have to use a dynamic query...
Hope this helps somebody, someday.

Related

How to create a stored procedure - Netezza Aginity

I am creating a test stored procedure but it does not work for me. What am I doing wrong?
I am using Aginity Workbench for PureData System for Analytics
CREATE OR REPLACE PROCEDURE OID_DB.SP_TEST_1(CHARACTER VARYING(8))
RETURNS CHARACTER VARYING(ANY)
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
PV_YYYYMMDD ALIAS FOR $1;
BEGIN
RETURN 'TEST_OK';
END;
END_PROC;
ERROR [HY000] 'CREATE OR REPLACE PROCEDURE OID_DB.SP_TEST_1(CHARACTER VARYING(8)) RETURNS CHARACTER VARYING(ANY) LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE PV_YYYYMMDD ALIAS FOR $1'
error > ^ found "" (at char 118) unterminated BEGIN_PROC string
I faced similar issue. Following solution worked for me:
Right click on the query window -> Options -> Change "Query Kind" from "Ordinary SQL" to "SP/Function".

FireDAC could not handle parameter names longer than 30 chars

I use Oracle database version 19.3.0 and it can handle parameter names longer than 30 chars. If I execute in Delphi FireDAC-procedure "ExecProc" to call Stored Procedure in SQL, Delphi throws "ORA-01036 : illegal Variable name/number" exception and calling of the procedure terminates prematurely, because one parameter name is longer then 30 chars.
Is there some FireDAC property to change this behavior without changing parameters name length?
"C:\Program Files (x86)\Embarcadero\Studio\19.0\source\data\firedac\FireDAC.Phys.Oracle.pas"
Solution: Change pbByName to pbByNumber
procedure TForm5.Button1Click(Sender: TObject); begin
FDStoredProc1.ParamBindMode := pbByNumber;
FDStoredProc1.FetchOptions.Items := [fiBlobs, fiDetails]; //This disables automatic fetching of parameters from server
FDStoredProc1.Params.CreateParam(ftString,'Averylongparamternamethathopefullyislongerthanthirtycharacters',ptInput);
FDStoredProc1.params.CreateParam(ftString,'outparam',ptOutput);
FDStoredProc1.Params[0].AsString := 'Hello World';
FDStoredProc1.ExecProc;
ShowMessage(FDStoredProc1.Params[1].AsString);
end;

TIBScript and local variables

I am working with Delphi 7 and Firebird 2.0. In my application I am using TIBScript components. The problem arises when I use local variables in the script. Firebird requires the names of local variables to be preceded by a colon in some cases. That’s where the problem lies in. The application stops showing the error message:
Dynamic SQL Error
SQL error code = -104
Token unknown - line 4, column 66
?
The token in question is the colon. Here is how my script looks like:
SET TERM ^ ;
EXECUTE BLOCK AS
DECLARE test_variable INT;
BEGIN
SELECT tt.id FROM test_table tt WHERE tt.name LIKE 'abc%' INTO :test_variable;
INSERT INTO test_table2(id, test_column)
VALUES(1, :test_variable);
INSERT INTO test_table3(id, test_column)
VALUES(1, :test_variable);
...
END^
SET TERM ; ^
The same script executes without any errors when run from IBExpert.
How can I use local variables in a TIBScript? Any help would be appreciated!
I want to add that this problem occurs only with variables inside an EXECUTE BLOCK construct. There is no problem with local variables in stored procedure and trigger definitions.
After executing the method TIBSQL.PreprocessSQL (Unit IBX.IBSQL line 2362), parameters marked with ":" on the front are replaced by "?". So you should use parameters without ":". Also I think it should be removed SET TERM. Instead, to set terminator value use the IBScript.Terminator property.
P.S. I watched unit IBX.IBSQL in Delphi 10.3 Rio.
this
EXECUTE BLOCK AS
DECLARE test_variable INT;
BEGIN
SELECT tt.id FROM USERS tt WHERE (tt.fname LIKE 'abc%') INTO test_variable;
END;
is executed properly when
IBScript.Terminator = ^;
Edit:
You can't execute INSERT with parameters in EXECUTE BLOCK using TIBScript component.
As Mark Rotteveel comented:
Unfortunately removing the colon is only an option in the into clause
in not with other occurrences of local variables or parameters.

Throwing error while printing record element string?

Throwing error while printing record element string using put why please help me to understand?
with ada.text_io;
use ada.text_io;
procedure main is
type my_rec is record
name:string(1..5)of integer;
end record;
var:my_rec;
begin
var.name:="hello";
put(var.name); -- why error?
end main;
error message is below
cc -c hello.adb
hello.adb:7:27: missing ";"
gnatmake: "main.adb" compilation error
hello.adb:7:27 is the coordinates of the error, so take a look in "hello.adb" on line 7 at character position 27.

Wrapping a Stored Procedure

I have created a Stored Procedure in Oracle (Via TOAD).
I need to deliver this procedure to some other developers. All is need to do is Wrap the procedure so that at basic level he/she should not be able to view the code.
At the same time, the developer should be able to create the procedure and execute/test it.
my procedure is saved in say FileName.sql whose content are like:
Create or Replace Procedure
IS
Declaration
Begin
Code
End;
Now i want this FileName.sql to be wrapped. So that the encrypted file can be send to other to check in different environment.
Please help me in how to wrap, and then how the other guy will be able to create the procedure, and execute the same.
Thanks in advance.
The Oracle WRAP utility does exactly that - allows you to encode a stored procedure in a form suitable for shipping.
The wrapped code is as portable as source code, but cannot be examined as plain text.
You will need access to the command line using a suitable system user (i.e. one that has access to the Oracle binary commands e.g. sqlplus etc.) and the basic syntax is:
wrap iname=input_file [ oname=output_file ]
If you do not specify any extensions, the default for input is .sql and output is .plb
Once you have generated a .plb file, you can execute it against the database to create your stored procedure.
See:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/wrap.htm#LNPLS016
http://docs.oracle.com/cd/B10500_01/appdev.920/a96624/c_wrap.htm
WARNING
WRAPencoded procedures are not completely secure - it is possible to "unwrap" them.
A better way of using WRAP is to put the procedure(s) you wish to protect in a package and WRAP the package definition.
Let's say your procedure is:
CREATE OR REPLACE PROCEDURE PR_OUTPUT_TEXT(
P_TYPE IN CHAR,
P_TEXT IN VARCHAR2
) IS
V_TYPE CHAR(3) := UPPER(P_TYPE);
BEGIN
IF V_TYPE = 'LOG' THEN
APPS.FND_FILE.PUT_LINE(APPS.FND_FILE.LOG, TO_CHAR(SYSDATE,'HH24:MI:SS')||' - '||P_TEXT);
ELSE
APPS.FND_FILE.PUT_LINE(APPS.FND_FILE.OUTPUT, P_TEXT);
END IF;
END PR_OUTPUT_TEXT;
you would normally call it using:
EXECUTE PR_OUTPUT_TEXT('LOG', 'Kittehz!!!')
In a package you would define the package body and the procedure thus:
CREATE OR REPLACE PACKAGE BODY USER.MYPACKAGE AS
PROCEDURE PR_OUTPUT_TEXT(
P_TYPE IN CHAR,
P_TEXT IN VARCHAR2
) IS
BEGIN
IF V_TYPE = 'LOG' THEN
APPS.FND_FILE.PUT_LINE(APPS.FND_FILE.LOG, TO_CHAR(SYSDATE,'HH24:MI:SS')||' - '||P_TEXT);
ELSE
APPS.FND_FILE.PUT_LINE(APPS.FND_FILE.OUTPUT, P_TEXT);
END IF;
END PR_OUTPUT_TEXT;
END MYPACKAGE;
and you would call the package using:
EXECUTE USER.MYPACKAGE.PR_OUTPUT_TEXT('LOG', 'ERMAHGERD KERTERNS!!!')
From documentation, to be precise, this is what you need to do :
Running the wrap Utility
For example, assume that the wrap_test.sql file contains the following:
CREATE PROCEDURE wraptest IS
TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
all_emps emp_tab;
BEGIN
SELECT * BULK COLLECT INTO all_emps FROM employees;
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id);
END LOOP;
END;
/
To wrap the file, run the following from the operating system prompt:
wrap iname=wrap_test.sql
The output of the wrap utility is similar to the following:
PL/SQL Wrapper: Release 10.2.0.0.0 on Tue Apr 26 16:47:39 2005
Copyright (c) 1993, 2005, Oracle. All rights reserved.
Processing wrap_test.sql to wrap_test.plb
If you view the contents of the wrap_test.plb text file, the first line is CREATE PROCEDURE wraptest wrapped and the rest of the file contents is hidden.
You can run wrap_test.plb in SQL*Plus to execute the SQL statements in the file:
SQL> #wrap_test.plb
After the wrap_test.plb is run, you can execute the procedure that was created:
SQL> CALL wraptest();
More information in docs