I have a procedure which takes as input a suffix of a table's name. Then, using execute format(), I pass this parameter to execute the dynamic query. The problem is that this parameter is the same throughout - I do not want to pass it x times as such:
execute format('SELECT table_%s.field1, table_%s.field2,table_%s.field3
FROM table_%s', inTableSuffix, inTableSuffix, inTableSuffix, inTableSuffix, ...)
I would like a format similar to the following:
execute format('SELECT table_%s.field1, table_%s.field2,table_%s.field3
FROM table_%s', inTableSuffix)
I understand that I can solve this problem using an alias to the table name but is there another alternative?
You can repeatedly address the positional arguments like this:
execute format('SELECT table_%1$s.field1
, table_%1$s.field2,table_%1$s.field3
FROM table_%1$s;', inTableSuffix);
Note: in this particular case, you can avoid repeating yourself by using an alias:
execute format('SELECT tx.field1
, tx.field2, tx.field3
FROM table_%s tx;', inTableSuffix);
#wildplasser already provided the syntax how to reference the same parameter repeatedly in format(). The code is still dangerous, though. You need to escape identifiers built from user input:
EXECUTE format('SELECT field1, field2, field3 FROM %I', 'table_' || inTableSuffix);
For the given example, you only need the parameter once anyway. The scope of dynamic queries executed with EXECUTE in plpgsql is limited to the query itself. Other variables or parameters of the function are not visible inside EXECUTE. Hence, there is not need to table-qualify columns in a dynamic query with a single table in the FROM clause.
But more importantly, %I is used in format() for identifiers to avoid syntax errors, misguided lower-casing or, worse, SQL injection! It double-quotes (only!) otherwise illegal identifiers, just like quote_ident() would.
Details:
SQL injection in Postgres functions vs prepared queries
Demonstrate SQL injection in PL/pgSQL
Are PostgreSQL column names case-sensitive?
Related
I know we can call the function from SQL if it doesn't contain out parameter or DML(except autonomous). But we can't call the procedure from SQL in any condition.
What is the reason for it?
Why can't we call the procedure from SQL? Any specific reason.
The reason is that the SQL ANSII standard specifies that only functions can be used in the SQL query.
ISO committee members did not define the use of procedures in SQL queries.
You can:
call dbms_output.put_line('Hello')
CALL is part of the SQL language.
Or we can embed a procedure in an inline function:
with function f (p varchar2)
return varchar2
as
begin
dbms_output.put_line('Hello');
return p;
end f;
select f('Demo')
from dual
If you mean a SELECT statement specifically, I can't see how you expect that to work. What result set would you expect a query like this to return?
select dbms_output.put_line('Hello')
from dual
or
select dbms_stats.gather_table_stats(user, table_name)
from user_tables
This isn't an arbitrary restriction by some standards committee. It just doesn't make any sense semantically.
You can call or execute a procedure easily in SQL. Both parametrized or non can be called.
EXEC dbo.procedure_name
I'm assuming, that you are asking about calling procedures from within other SQL statements (not just call a procedure on its own, which is obviously possible).
Why? That's a matter of opinion, and you would have to ask Oracle DB architects for a real cause.
It would seem, that introducing procedure calls into all possible SQL statements, would bring both syntax and implementation complexity, while not necessarily bringing much more value. Usually there are alternatives, which are not much harder to use, while allowing the same outcome.
In case of a query (a SELECT statement), the result should be a data set, and no changes in the database state (data or structure) should be done. A PL/SQL procedure does not return a data set, and can change the database state.
If you are in a situation, where the procedure call is needed to prepare the data, you'd like to query, then you have the possibility to call the procedure first, and then query the database.
You can also write a procedure, which will have an output parameter of a cursor reference, which will effectively give you a query result. (For an ad hoc case, you could use parameterized anonymous PL/SQL block.)
You can also write a tabular function, where you can do complex data processing, using PL/SQL, and return a data set. Such function can be used in a query.
If you are asking also about other types of SQL statements, then you can always call DML (INSERT / UPDATE / DELETE / MERGE), DDL (CREATE / ALTER / DROP) or DCL (GRANT / REVOKE) from a procedure or an anonymous PL/SQ block, that does those and allows you to mix PL/SQL logic in. No need to do this the other way (introducing PL/SQL into DML / DDL / DCL).
It looks like with postgres, there are two ways to prepare and execute prepared statements. You can use the functions PQprepare and PQexecPrepared directly from libpq; or you can issue SQL statements: PREPARE and EXECUTE. The statement names are the same across either method so you can use PQPrepare to prepare a statement and then execute it by issuing an EXECUTE query (or use a PREPARE query and then execute it with PQexecPrepared).
So the two approaches (library functions vs SQL queries) are equivalent. However, it looks like when you use PQexecPrepared, the query column of pg_stat_activity is the underlying prepared statement with placeholders. So something like:
SELECT * from users where name in ($1, $2, $3);
But when you use an EXECUTE query, pg_stat_activity contains the SQL of the EXECUTE, like:
EXECUTE user_query('joe', 'bob', 'sally');
Questions
Is there a way to get the same output for the two different ways of executing prepared statements?
Is there a way to see both the query, and the bound parameters when executing prepared statements?
You are right that both ways to execute a prepared statement do the same thing under the hood, but since they are called in different ways on the SQL level, they look different in pg_stat_activity. There is no way to change that.
To get the statement and the parameters you must resort to the log file.
In the case of PQexecPrepared, you will see the statement as a LOG message and the parameters as its DETAIL if you turn on statement logging.
With PREPARE and EXECUTE, you have no choice but to find the PREPARE earlier in the session (both have the same session identifier, that is %c in log_line_prefix).
I am working on an extension of a PostgreSQL library that takes a string representation of a query as input. Basically I need to instantiate the resulting table that this string-based query produces, modify it, and then pass it to another function.
Right now I am just trying to get the query instatiated as a temporary table, so I am using this sample query:
CREATE TEMPORARY TABLE pgr_table (seq INTEGER, path_seq INTEGER, node INTEGER, edge BIGINT, cost DOUBLE PRECISION, agg_cost DOUBLE PRECISION);
EXECUTE 'SELECT gid AS id, source, target, cost, reverse_cost FROM ways;' INTO pgr_table;
But this results in a syntax error, just after the EXECUTE command. Am I not using it correctly?
By the way, I am aware of the dangers of SQL injection and using EXECUTE willy-nilly. The queries that I am making are not designed for front-end use, and I am following the design patterns already set forth by the library which I am modifying.
you confuse SQL execute and plpgsql execute - first to execute prepared statement and is run in SQL (as you try). second is a part of function plpgsql code
https://www.postgresql.org/docs/current/static/sql-execute.html
EXECUTE — execute a prepared statement
https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
Oftentimes you will want to generate dynamic commands inside your
PL/pgSQL functions, that is, commands that will involve different
tables or different data types each time they are executed. PL/pgSQL's
normal attempts to cache plans for commands (as discussed in Section
42.10.2) will not work in such scenarios. To handle this sort of problem, the EXECUTE statement is provided:
examples:
t=# prepare s as select now();
PREPARE
t=# execute s;
now
-------------------------------
2017-12-14 12:47:28.844485+00
(1 row)
and plpgsql:
t=# do
$$
declare
t text;
begin
execute 'select now()' into t;
raise info '%',t;
end;
$$
;
INFO: 2017-12-14 12:48:45.902768+00
DO
updtae
to avoid injection using dynamic code, use function format
https://www.postgresql.org/docs/current/static/functions-string.html
Format arguments according to a format string. This function is
similar to the C function sprintf.
I have a procedure, based on the parameters, the where condition would differ.
The OUT parameters have to be INTO clause so that I can return the columns from the procedure.
Rather than having SQL condition for each if condition, what is the efficient way of doing this.
It looks to me more like a design question.
So it depends on what you need to achieve and how you want to organize your code.
Possibilities
1- your "if" chain of queries in the same procedure
2- one procedure for each query
3 - if the differencies between the "where" parts are not so big use sql constructs, including unions, case , and\or etc to let coexist different cases in one query
4- build sql dynamically and use execute immediate
Usually i don't like the 1, i would try with 3 or 4, then proceed with 2 if i can't.
EDIT
With dynamic sql, for getting out results you can do
EXECUTE IMMEDIATE stmt into o_total_count,o_total_sum,o_hold_status,o_normal_status;
In case you have input params for the query, you have to mark them with : and then add the USING clause with the appropriate input param.
Example
EXECUTE IMMEDIATE 'select count(*) from departments where department_id=:id' INTO l_cnt USING l_dept_id;
I did not see any duplicate questions but wondering if somebody can provide some good examples and specially best practices around these.
Prepared Statements are precompiled statements that you can run multiple times against on the database, and SQLServer won't parse or generate a different execution plan each time you run it. Usually, you run prepared statement in a client context (using JDBC, ADO.NET, ODBC or any other client access technology).
A prepared statement in Java (using JDBC, of course) will be something like:
PreparedStatement ps = conn.prepareStatmente("insert into t(field1) values (?)");
ps.setString(1, "Hello");
ps.executeUpdate();
ps.setStrgin(2, "World");
ps.executeUpdate();
ps.close();
// two rows will be inserted into table t:
// field1 => "Hello"
// field1 => "world"
Dynamic SQL is the ability to run any SQL sentence stored in a dynamic variable (i.e. a string) inside a stored procedure or function in SQLServer. You can find some examples in the link provided.
It'd be easier to explain with some context...
In Java, PreparedStatements are SQL statements in a Java String and supports placeholders you can populate without worrying about escaping single quotes. .NET also has PreparedStatement syntax:
Prepared execution is commonly used by applications to execute the same parameterized SQL statement repeatedly. Prepared execution is faster than direct execution for statements executed more than three or four times because the statement is compiled only once, while statements executed directly are compiled each time they are executed. Prepared execution can also provide a reduction in network traffic because the driver can send an execution plan identifier and the parameter values, rather than an entire SQL statement, to the data source each time the statement is executed.
A step short of using a Stored Procedure...
MySQL's dynamic SQL syntax is also called PreparedStatements...
Dynamic SQL
Dynamic SQL is basically any SQL declared as a string data type - it can be customized before execution. The need for using dynamic SQL comes when you want to do things like dynamic column and/or table references. For example, no SQL supports a string variable to represent the table in the FROM clause (Table Valued Variables are an exception, where supported).
It's important to know the difference between EXEC and EXEC sp_executesql with regard to dynamic SQL on SQL Server. EXEC sp_executesql was added in SQL Server 2005, and you can read more about dynamic SQL on SQL Server in the excellent article: The Curse and Blessings of Dynamic SQL
PreparedStaement is a language construct that provides pre-compiled queries that has already been explained in above answers. One very important benefit of using prepared statements is that they save you from malicious SQL injection attacks. How? you only have placeholder in which you can put in values and no other way to alter the query (pre-compiled), whereas in case of Statements, you can alter the query string. Example:
I have a query to update a table -
UPDATE table_name SET col1 = 40 WHERE id = 'A001';
This can be altered (maliciously) as -
UPDATE table_name SET col1 = 40 WHERE id = 'A001'; DROP TABLE table_name;
And your table is gone!
Dynamic queries are a database construct that helps you to write a query in which you can use bind variables rather using values. These are particularly used in PL/SQL code. Also useful in executing DDL statements. Example code (Oracle):
ip_job_name := 'APP_EXTRACT';
lv_query := 'SELECT 1 FROM user_table WHERE table_name = :tab_name';
BEGIN
EXECUTE IMMEDIATE lv_query INTO lv_tab USING ip_job_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || ip_job_name;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;