I am accessing AWS RedShift through DBI and DBD::Pg module in Perl and I have some trouble with SQL bind variable. I call prepare with sql statement (? in the place of variable) first and then I call execute with the variable array which needs to be mapped to ? but it doesn't work. It simply spits "syntax error".
My understanding is that this bind variable needs to be supported by the driver and the database itself so I am not sure whether it is a problem of the driver or RedShift but then I am not sure whether my understanding (bind variable support depends on the driver and underlying database) is correct. If someone could clarify, that would be great.
Prepared statements are supported, but the correct notation for parameters is $1, $2, ...
From the Redshift Developer Guide:
Prepared statements can take parameters: values that are substituted
into the statement when it is executed. To include parameters in a
prepared statement, supply a list of data types in the PREPARE
statement, and, in the statement to be prepared itself, refer to the
parameters by position using the notation $1, $2, ... When executing
the statement, specify the actual values for these parameters in the
EXECUTE statement.
Related
I am investigating a possible SQL injection bug in some COBOL code. The code uses host variables to submit the statement to a DB2 database. e.g.
EXEC SQL INSERT INTO TBL (a, b, c) VALUES (:x, :y, :z) END-EXEC
Can anyone tell me if this method would be vulnerable to an SQLi attack or if the way COBOL/DB2 parses the host variables means that it would be impossible to execute?
Every thing I read suggests there are better ways to protect against SQLi but the IBM website does mention using host variables but doesn't explain if it would totally mitigate against the attack.
Static statements with host variables are not susceptible to SQL injection attacks.
Non-parameterized dynamic statements are what you need to worry about...
They would look something like so: (my COBOL is rusty)
STRING "INSERT INTO TBL (a,b,c) VALUES ("
X ", "
Y ", "
Z ")" INTO WSQLSTMT.
EXEC SQL PREPARE MYSTMT FROM :WSQLSTMT END-EXEC.
EXEC SQL EXECUTE MYSTMT END-EXEC.
Note that you could use EXECUTE IMMEDIATE, in place of the two step PREPARE and EXECUTE
In contrast, a parameterized dynamic query looks like:
STRING "INSERT INTO TBL (a,b,c) VALUES (?, ?, ?)" INTO WSQLSTMT.
EXEC SQL PREPARE MYSTMT FROM :WSQLSTMT END-EXEC.
EXEC SQL EXECUTE MYSTMT USING :X, :Y, :Z END-EXEC.
In summary, a static query with host variables like you original posted is SAFE as is a parameterized dynamic query. A non-parameterized query that directly uses the user input to build the SQL statement to execute is NOT SAFE.
The key thing to understand is that the statement must be compiled (PREPARED) in advance before the run-time values of the variables come into play. In you original static statement, the statement is prepared automatically at compile time.
Side note, since a static statement is prepared at compile time, it performs better than a dynamic statement prepared at run time. So it's usually best to use static statements whenever possible.
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();
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.
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?
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.