User defined variables in PostgreSQL - postgresql

I have the following MySQL script which I want to implement in PostgreSQL.
SET #statement = search_address_query;
PREPARE dynquery FROM #statement;
EXECUTE dynquery;
DEALLOCATE PREPARE dynquery;
How can I define user defined variable "#statement" using PostgreSQL.

Postgres does not normally use variables in plain SQL. But you can do that, too:
SET foo.test = 'SELECT bar FROM baz';
SELECT current_setting('foo.test');
Read about Customized Options in the manual.
In PostgreSQL 9.1 or earlier you needed to declare custom_variable_classes before you could use that.
However, You cannot EXECUTE dynamic SQL without a PL (procedural language). You would use a DO command for executing ad-hoc statements (but you cannot return data from it). Or use CREATE FUNCTION to create a function that executes dynamic SQL (and can return data in any fashion imaginable).
Be sure to safeguard against SQL injection when using dynamic SQL.
Related:
Is there a way to define a named constant in a PostgreSQL query?

Related

PgAdmin won't allow RAISE NOTICE

When I try to use RAISE NOTICE in a Query tool in PgAdmin I just get "ERROR: syntax error at or near "RAISE"". This is stopping defining a stored procedure which uses RAISE NOTICE.
I have simply typed the following into a Query Tool window:
RAISE NOTICE 'Bob';
I am using PgAdmin 6.3 (the latest), just updated from v4.5 which had the same problem.
RAISE is part of pl/pgsql, Postgres's default procedural language. It is not available in a direct SQL context, or any function or stored procedure defined with LANGUAGE sql rather than LANGUAGE plpgsql.
If you're used to a different DBMS like MySQL or SQL Server, you might expect to have procedural code (variables, conditionals, loops, etc) available by default, but that's not how Postgres works. In order to use procedural code, you need to be inside a function, stored procedure, or DO statement.

Assigning variable in SQL editor context in Firebird

I would like to know if it is possible in Firebird to assign and reference a variable in SQL Editor context.
To be clear, I present a code sample in MySQL that do what I want.
SET #var = 10;
SELECT #var;
Firebird only supports variables in PSQL (Procedural SQL), including anonymous procedures (EXECUTE BLOCK). There is no direct equivalent of using variables like in MySQL in DSQL (Dynamic SQL, the normal 'SQL' you use with Firebird).
The closest alternative is to use the context variables using RDB$GET_CONTEXT and RDB$SET_CONTEXT. The near equivalent of your code would be
select RDB$SET_CONTEXT('USER_TRANSACTION', 'var', 10) from RDB$DATABASE;
select RDB$GET_CONTEXT('USER_TRANSACTION', 'var') from RDB$DATABASE;
Be aware, a context variable is stored and retrieved as VARCHAR(255), so if you need to retrieve an integer, you will need to explicitly cast it.
Instead of 'USER_TRANSACTION', with scope limited to the current transaction, you can also use 'USER_SESSION', with scope limited to the current connection.
There is no such thing as "Editor context". Notepad, Word, SynWrite - you can edit anything in them, SQL or not. An editor is just an editor, there is no special context, SQL-wise, in it.
In editor you edit all the SQL texts. DSQL statements, PSQL scripts, everything. Editor does not matter, only difference between DSQL vs PSQL matters here, so read about them in the documentation. Editor has no its own SQL context.
Language-native variables only exist in PSQL context, that is "Procedural" SQL, language used for writing stored procedures, triggers, execute blocks, etc. Also, SQL functions, starting with Firebird 3.
Example from https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-psql.html
CREATE OR ALTER PROCEDURE DEPT_BUDGET (
DNO CHAR(3))
RETURNS (
TOT DECIMAL(12,2))
AS
DECLARE VARIABLE SUMB DECIMAL(12,2);
DECLARE VARIABLE RDNO CHAR(3);
DECLARE VARIABLE CNT INTEGER;
BEGIN
TOT = 0;
SELECT
BUDGET
FROM
DEPARTMENT
WHERE DEPT_NO = :DNO
INTO :TOT;
SELECT
COUNT(BUDGET)
FROM
DEPARTMENT
WHERE HEAD_DEPT = :DNO
INTO :CNT;
IF (CNT = 0) THEN
SUSPEND;
FOR
SELECT
DEPT_NO
FROM
DEPARTMENT
WHERE HEAD_DEPT = :DNO
INTO :RDNO
DO
BEGIN
EXECUTE PROCEDURE DEPT_BUDGET(:RDNO)
RETURNING_VALUES :SUMB;
TOT = TOT + SUMB;
END
SUSPEND;
END
Apart from PSQL in Firebird there are more languages ("contexts"): DSQL (Dynamic SQL), ESQL (Embedded SQL) and pre-SQL native query language. Of those only DSQL is of any general use nowadays.
In DSQL you have no language-level variables, but you have functions to set/fetch parts of context: RDB$GET_CONTEXT() and RDB$SET_CONTEXT().
https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-functions-scalarfuncs.html#fblangref25-functions-workcontext
select rdb$set_context('USER_SESSION', 'MyVar', 493) from rdb$database
and later
select rdb$get_context('USER_SESSION', 'MyVar') from rdb$database
You can not change 'USER_SESSION' here, as that is the only context you are allowed to write something, other contexts for reading only. But you are free to change the 2nd parameter as you like - that is the name of textual environment variable you set and retrieve.
UPD. I was wrong, there is one more writable context, 'USER_TRANSACTION', see 2.0.7 Release Notest at https://firebirdsql.org/file/documentation/release_notes/html/rlsnotes207.html#dml-dsql-context-ns
Read docs by the two links above and also read the file situated like
c:\Program Files (x86)\Firebird\Firebird_2_1\doc\sql.extensions\README.context_variables2.txt
adjust the path for specific Firebird version on your computer. You can see there full list of contexts (first parameter allowed values) available in your FB version.
However, since you want to use language-native variables, think about, using PSQL instead - see EXECUTE BLOCK in Firebird documentation and my first example. If you do not need to return more than one different datasets from your script, then wrapping it all into one EB for the sake of having variables may suit you better.

Calling functions with exec instead of select

Is the default way of calling a function select * from my_function()?
I ask because I have built a function that doesn't return anything, just inserts data into a table and (coming from a SQL Server background) it "feels" strange to call it with select * from...
I was expecting something like exec my_function()
use PERFORM statement - http://www.postgresql.org/docs/current/static/plpgsql-statements.html
Sometimes it is useful to evaluate an expression or SELECT query but
discard the result, for example when calling a function that has
side-effects but no useful result value. To do this in PL/pgSQL, use
the PERFORM statement
so it's just
DO $$ BEGIN
PERFORM my_function();
END $$;
PostgreSQL 11:
PostgreSQL 11 supports true stored procedures as pointed out by #AbdisamadKhalif . They support in-procedure transaction control.
Older versions:
Yes, that's the standard way, and yes it's weird.
Usually you'd write such functions as stored procedures and invoke them with the CALL or EXECUTE command. PostgreSQL does not support true stored procedures (multiple result sets, autonomous transactions, and all that) though, only sql-callable user-defined functions.
So the workaround is to SELECT function_name() using the PostgreSQL extension syntax that omits FROM, or SELECT 1 FROM function_name(); to be (somewhat) more standard.
The ODBC driver, JDBC driver, etc understand the {call func_name()} escape syntax and automatically translate it to an underlying SELECT.
You will use from when the function returns a set. If the function returns void just do
select my_function();

What is the purpose of pgScript in PostgreSQL?

I have failed to understand the need for pgScript, which could be executed using pgAdmin tool. When it should be used? What it can do that plpgSQL cannot do? What is equivalent of it in Microsoft SQL Server?
pgScript is a client-side scripting language, while pl/PgSQL runs on the server. This means they have entirely different use cases. For example, PgScript can manage transaction status while pl/PgSQL cannot, but pl/Pgsql can be used to extend the language of SQL while pgScript cannot do that.
Additionally it means the two will handle many other things quite differently ranging from query plans to dynamic SQL, and while pgScript requires round trips between queries pl/Pgsql does not.
One use for pgScript is to define variables and use them later in your SQLs.
For example, you could do something like this:
declare #mytbl, #maxid;
set #mytbl = 'sometable';
set #maxid = 2500;
set #res = select count(*) from #mytbl where id <= #maxid;
print #res;
This approach is to just have any variables you want to change at the top of your script, rather than those getting buried deep inside complex SQL queries.
Of course, pgScript is a feature available only inside PgAdmin III client like #{Craig Ringer} mentioned in his comment.
I used DDL script generator from Toad Data Modeler.
I ran the script using normal query execution in PgAdmin-III but it kept giving me error:
"ERROR: relation "user" already exists SQL state: 42P07".
I ran Execute pgScript in PgAdmin-III and it worked fine.

shell command for executing stored procedure in DB2 OS400

what is the shell command for executing stored procedure in DB2 OS400.
CALLPRC PRC(SPNAME) PARM('','',5,'','') RTNVAL()
what is this one??
Assuming you've got a stored procedure called SPNAME, here's how you'd run it through SQL on DB2:
CALL SPNAME('', '', 5, '', '');
This of course assumes that you've already got a database connection through which you can execute SQL statements.
A couple of things you'll probably have to worry about:
You will probably have to specify the program's library like this: CALL LIBNAME.SPNAME(...). Or you can use SET PATH=LIBNAME to provide a list of libraries to search.
You will want to look into parameter binding. This will allow you to pass input values to the procedure and get back the output values.
This link explains how to execute a stored procedure in PHP using ODBC.