UTL_FILE for dummies (me) - oracle-sqldeveloper

Bit of a newbie with SQL developer, trying to figure out both Packages, and UTL_File package at the same time.
I've created a package, and am trying to write a procedure that creates a file, but I'm a bit unsure on when/where to declare my variables. Following procedure is in my Package body, but doesn't work.
PROCEDURE NewFile IS
DECLARE
v_file utl_file.file_type;
v_filename VARCHAR2(20) := 'TIMtest.dat';
BEGIN
v_file := utl_file.fopen ('TIM_DIR', v_filename, 'A');
utl_file.put_line(v_file, 'Hello World # ' || to_char(sysdate));
utl_file.fclose(v_file);
END NewFile;
The error I get is:
Error(13,1): PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior external language The symbol "begin" was substituted for "DECLARE" to continue.
Evidently the problem is with where/how I'm declaring my variables, but I'm not sure where they go, if not there.

Related

Why does using the IF-ENDIF block in this DB2 function cause

Why does using the IF statement in this function result in error 42601 [SQL0104], as shown below..? This is DB2-400 for i v7r3m0.
SQL Error [42601]: [SQL0104] Token <END-OF-STATEMENT> was not valid. Valid tokens: ;.
The code example I provide below executes without error until the IF statement is uncommented. I've tried moving the semicolons around and even removing them, but then the errors get worse and begin pointing to later statements being invalid.
I've checked the IBM documentation for IF on v7r3, and my syntax seems to be correct. Other code examples follow the same syntax as that and mine. I'm stumped.
CREATE OR REPLACE FUNCTION F_CERT.CERT_UPC_COMMON_DESC (UPC NUMERIC(14))
RETURNS INTEGER
LANGUAGE SQL
GLOBAL DETERMINISTIC
NO EXTERNAL ACTION
NOT FENCED
ALLOW PARALLEL
BEGIN
DECLARE RETVAL INTEGER DEFAULT 0 ;
DECLARE UPC_COUNT INTEGER DEFAULT 0 ;
DECLARE UPC_LIST CURSOR FOR
SELECT COUNT(*)
FROM F_CERTOB.BEERXT
WHERE BXUPCR=UPC
;
OPEN UPC_LIST ;
FETCH UPC_LIST INTO UPC_COUNT ;
CLOSE UPC_LIST ;
-- IF UPC_COUNT > 0 THEN
-- -- OTHER
-- -- COMMANDS
SET RETVAL = UPC_COUNT ;
-- END IF ;
RETURN RETVAL ;
END ;
SELECT F_CERT.CERT_UPC_COMMON_DESC (793936791660) AS C FROM SYSIBM.SYSDUMMY1 ;
EDIT:
Here is a second example; a trimmed-down version. As with the code above, everything is fine until the IF statements are uncommented:
CREATE OR REPLACE FUNCTION F_CERT.CERT_UPC_COMMON_DESC (UPC NUMERIC(14))
RETURNS INTEGER
LANGUAGE SQL
BEGIN
DECLARE RETVAL INTEGER DEFAULT 0 ;
-- IF 1=1 THEN
SET RETVAL = 1 ;
-- ELSE
SET RETVAL = 100 ;
-- END IF ;
RETURN RETVAL ;
END ;
SELECT F_CERT.CERT_UPC_COMMON_DESC (12345) AS C FROM SYSIBM.SYSDUMMY1 ;
I've continued searching since my OP, and I finally found the exact solution
here.
The issue is the statement delimiter. A conflict arises when the function contains flow-control and similarly structured statements that span multiple lines. In my code example, the compiler stops at END IF; and thinks that's all there is, instead of continuing to the END; of the function.
My SQL client is DBeaver 5.2.5, and it does have some functionality to run statements & scripts in different ways. This article gave me the idea to try running my CREATE script with the different actions of DBeaver, and I discovered I could make it work if I highlighted the whole script from CREATE to END but not including the trailing semicolon. Then I used Execute Statement {Ctrl+Enter} instead of the usual Execute Sctipt {Alt+X}. And it finally worked..!! But that seemed "kludgy" so I continued searching for a solution.
Then I found the imperfect, but perfectly acceptable solution in the main article mentioned above. I followed the directions to change the settings in my DBeaver client, and edited my code as shown below (notice the # characters). And then it finally worked..!! I could run the whole script, including the SELECT statement, and was able to do so with the usual Execute Statement {Alt+X} keystroke that I've become accustomed to.
CREATE OR REPLACE FUNCTION F_CERT.CERT_UPC_COMMON_DESC (UPC NUMERIC(14))
RETURNS INTEGER
LANGUAGE SQL
BEGIN
DECLARE RETVAL INTEGER DEFAULT 0;
IF 1=0 THEN
SET RETVAL = 1;
ELSE
SET RETVAL = 100;
END IF;
RETURN RETVAL;
END #
SELECT F_CERT.CERT_UPC_COMMON_DESC (793936791660) AS C FROM SYSIBM.SYSDUMMY1 #

how to declare a date (with time) variable in pl/sql

I want to use a date( DD/MM/YYYY HH:MI:SS ) variable in pl/sql. I'm using the following code but it doesn't work :
BEGIN
declare dateMig date ;
dateMig := to_date('19/05/2017 05:05:00', 'DD/MM/YYYY HH:MI:SS');
exec P_MY_PROC(100,'CHECK',dateMig);
END;
Can anyone help please? what am I doing wrong?
It would be helpful if you could explain what you mean by "doesn't work" - i.e. any error messages and/or unexpected results that you get.
However, there are a couple of obvious things wrong with your procedure:
You have the declaration section inside the execution block - that's not going to work for what you're wanting to do. PL/SQL programs consist of the declaration section, the execution section and the exception section in that order.
You're attempting to call a procedure using exec inside the PL/SQL program. That's not going to work as exec (or, to give it its full name, execute) is a SQL*Plus command not a PL/SQL command, and it allows you to run a procedure from the command line without having to nest it in a begin/end block. In PL/SQL you don't need to use exec.
So, your code should look something like:
declare
datemig date;
begin
datemig := to_date('19/05/2017 05:05:00', 'dd/mm/yyyy hh24:mi:ss');
p_my_proc(100, 'CHECK', datemig);
end;

I/O File Operations in Postgresql

I am brand new to PostgreSQL and I need someone to point me in
the right direction on how to write the results of a function to a text
file. Is it possible to do this within the PostgreSQL PL/pgSQL
language? I have done this before in Oracle using the UTL_FILE commands
and I was hoping that PostgreSQL had similar functionality. Thanks in advance for any help that you can give.
Kindly provide some examples of file operations.
CREATE OR REPLACE FUNCTION NP_AC015_FETCH.proc_log (P_MSG text, P_MODE integer default 1) RETURNS VOID AS $body$
DECLARE
V_F_IS_OPEN boolean; --IF LOG FILE IS ALREADY OPEN THIS IS SET TO TRUE
V_LOG_MSG varchar(32767); --LOG FILE NAME
V_LOG_DIR varchar(30) := 'ND_GANJIS_LOG_DIR'; --LOG DIRECOTY
vTemp UTL_FILE.FILE_TYPE;
BEGIN
select get_var('GM_LOG_FILE') INTO vTemp;
V_F_IS_OPEN := utl_file.is_open(vTemp);
if not V_F_IS_OPEN then
-- Log File Open
-- 32767 IS THE MAXIMUM NUMBER OF CHARACTERS PER LINE, INCLUDING THE NEWLINE CHARACTER, FOR THIS FILE.
vTemp := UTL_FILE.FOPEN(V_LOG_DIR, 'NIA_PLSQL_'||to_char(clock_timestamp(), 'yyyymmdd')||'.log', 'A', 32767);
end if;
-- LOG MSG TO BE WRITTEN TO THE LOG FILE
V_LOG_MSG := TO_CHAR(CURRENT_TIMESTAMP, 'yyyy/mm/dd hh24:mi:ss:ff3') ||' '|| P_MSG;
--Output messages to a file
UTL_FILE.PUT_LINE(vTemp, V_LOG_MSG);
--Closing Log File
if P_MODE = current_setting('NP_AC015_FETCH.PV_LOG_CLOSE_MODE')::pls_integer and utl_file.is_open(vTemp) then
utl_file.fclose(vTemp);
end if;
--HERE THE EXCEPTION PART IS NOT INCLUDED,
--Reason: PROGRAM WILL GO ON INFINITE LOOP IF SOME ERROR OCCURS HERE, BECAUSE, EACH EXCEPTION WRITES INTO
--LOG FILE, USING THIS PROCEDURE.
exception
when others then
RAISE EXCEPTION '%', dbms_utility.format_error_backtrace||chr(10)||dbms_utility.format_error_stack||chr(10)||dbms_utility.format_call_stack, true;
END;
$body$
LANGUAGE PLPGSQL;
You can install the adminpack contrib module and use the function pg_file_write(filename text, data text, append boolean).
Note that this function is restricted to superusers, but you can create a SECURITY DEFINER function owned by a superuser that provides the necessary functionality to the users you choose.

Variables inside PSQL script without creating a Function

I'm trying to get a PSQL script running using variables in an example like the one below without declaring functions and having to call them.
DECLARE
result TEXT;
BEGIN
SELECT INTO result name
FROM test;
RAISE NOTICE result;
END;
Where table test only has 1 row and column. Is this possible without having to wrap this script inside a function. This will allow me to call the script via say command line easier.
Thanks guys.
You can use DO to create and execute an anonymous function:
DO executes an anonymous code block, or in other words a transient anonymous function in a procedural language.
Something like this:
do $$
declare result text;
begin
select name into result from test;
raise notice '%', result;
end;
$$;
I also fixed your raise notice.
If you just want to dump the single value from the table to the standard output in a minimal format (i.e. easy to parse), then perhaps --tuples-only will help:
-t
--tuples-only
Turn off printing of column names and result row count footers, etc. This is equivalent to the \t command.
So you could say things like this from the shell:
result=$(echo 'select name from test;' | psql -t ...)

PostgreSQL Syntax error in PGAdmin

I am new to PostgreSQL and am using the query tool in PGAdmin. I'm trying to run pgsql queries that use variables, but I can't seem to get the syntax right.
Here's a sample query that gives a syntax error:
DECLARE
num INTEGER;
BEGIN
num := 3;
PRINT num;
END;
Update:
Ok, let me try and explain. I come from a SQL server background. In the management studio, I can open a query window and play with (T)-SQL queries.
For example, I can write something like this:
DECLARE #num INT
SET #num = 3
SELECT #num
I know this is a dumb example, but I'm just trying to declare a variable and do something with it. I'm trying to familiarise myself with PL/PGSQL.
Update, again:
It's me again. I'm trying the script below and get a "[ERROR ] 7.0-2: syntax error, unexpected character". Is this meant to work in PGAdmin?
DECLARE
num INTEGER;
BEGIN
num := 3;
RAISE NOTICE '%', num;
END;
You can use the do statement. For example:
do $$
declare
num integer := 10;
begin
RAISE INFO 'VARIABLE: %', num;
end;
$$language plpgsql;
When you use pgadmin you have to use the button EXECUTE QUERY instead of
Execute pdScript, as it is explained here:
http://postgresql.1045698.n5.nabble.com/PgAmin3-Anonymous-code-block-can-t-be-executed-by-pressing-quot-Execute-PG-script-quot-button-td5771073.html
The documentation for do statements is here:
http://www.postgresql.org/docs/9.3/static/sql-do.html
Just to rephrase and "concretize" what others say:
There are no inline procedures in PostgreSQL. There is also no PRINT statement. You have to:
CREATE OR REPLACE FUNCTION test() RETURNS void AS $$
DECLARE
num INTEGER;
BEGIN
num := 3;
RAISE NOTICE '%', num;
END;
$$ LANGUAGE plpgsql;
SELECT test();
If you're trying to print out num (say, for debugging), you could try:
RAISE NOTICE '%', num;
http://www.postgresql.org/docs/8.4/static/plpgsql-errors-and-messages.html
PRINT doesn't mean anything in PL/pgSQL.
I have no idea what you are trying to achieve. PostgreSQL doesn't support this kind of syntax. Similar keywords (except PRINT?!) are in PL/pgSQL which is procedural language for building FUNCTIONS, not for writing stand-alone SQL queries.
Postgres doesn't support anything like that by itself (yet). psql (the official command line client) has some rudimentary scripting.
The best option for you is pgAdmin which already has scripting built-in.