Difference between language sql and language plpgsql in PostgreSQL functions - sql

Am very new in Database development so I have some doubts regarding my following example:
Function f1() - language sql
create or replace function f1(istr varchar)
returns text as $$
select 'hello! '::varchar || istr;
$$ language sql;
Function f2() - language plpgsql
create or replace function f2(istr varchar)
returns text as $$
begin select 'hello! '::varchar || istr; end;
$$ language plpgsql;
Both functions can be called like select f1('world') or select f2('world').
If I call select f1('world') the output will be:
`hello! world`
And output for select f2('world'):
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function f11(character varying) line 2 at SQL statement
********** Error **********
I wish to know the difference and in which situations I should use language sql or language plpgsql.
Any useful link or answers regarding functions will much appreciated.

SQL functions
... are the better choice:
For simple scalar queries. Not much to plan, better save any overhead.
For single (or very few) calls per session. Nothing to gain from plan caching via prepared statements that PL/pgSQL has to offer. See below.
If they are typically called in the context of bigger queries and are simple enough to be inlined.
For lack of experience with any procedural language like PL/pgSQL. Many know SQL well and that's about all you need for SQL functions. Few can say the same about PL/pgSQL. (Though it's rather simple.)
A bit shorter code. No block overhead.
PL/pgSQL functions
... are the better choice:
When you need any procedural elements or variables that are not available in SQL functions, obviously.
For any kind of dynamic SQL, where you build and EXECUTE statements dynamically. Special care is needed to avoid SQL injection. More details:
Postgres functions vs prepared queries
When you have computations that can be reused in several places and a CTE can't be stretched for the purpose. In an SQL function you don't have variables and would be forced to compute repeatedly or write to a table. This related answer on dba.SE has side-by-side code examples for solving the same problem using an SQL function / a plpgsql function / a query with CTEs:
How to pass a parameter into a function
Assignments are somewhat more expensive than in other procedural languages. Adapt a programming style that doesn't use more assignments than necessary.
When a function cannot be inlined and is called repeatedly. Unlike with SQL functions, query plans can be cached for all SQL statements inside a PL/pgSQL functions; they are treated like prepared statements, the plan is cached for repeated calls within the same session (if Postgres expects the cached (generic) plan to perform better than re-planning every time. That's the reason why PL/pgSQL functions are typically faster after the first couple of calls in such cases.
Here is a thread on pgsql-performance discussing some of these items:
Re: pl/pgsql functions outperforming sql ones?
When you need to trap errors.
For trigger functions.
When including DDL statements changing objects or altering system catalogs in any way relevant to subsequent commands - because all statements in SQL functions are parsed at once while PL/pgSQL functions plan and execute each statement sequentially (like a prepared statement). See:
Why can PL/pgSQL functions have side effect, while SQL functions can't?
Also consider:
PostgreSQL Stored Procedure Performance
To actually return from a PL/pgSQL function, you could write:
CREATE FUNCTION f2(istr varchar)
RETURNS text AS
$func$
BEGIN
RETURN 'hello! '; -- defaults to type text anyway
END
$func$ LANGUAGE plpgsql;
There are other ways:
Can I make a plpgsql function return an integer without using a variable?
The manual on "Returning From a Function"

PL/PgSQL is a PostgreSQL-specific procedural language based on SQL. It has loops, variables, error/exception handling, etc. Not all SQL is valid PL/PgSQL - as you discovered, for example, you can't use SELECT without INTO or RETURN QUERY. PL/PgSQL may also be used in DO blocks for one-shot procedures.
sql functions can only use pure SQL, but they're often more efficient and they're simpler to write because you don't need a BEGIN ... END; block, etc. SQL functions may be inlined, which is not true for PL/PgSQL.
People often use PL/PgSQL where plain SQL would be sufficient, because they're used to thinking procedurally. In most cases when you think you need PL/PgSQL you probably actually don't. Recursive CTEs, lateral queries, etc generally meet most needs.
For more info ... see the manual.

just make the select query you wrote inside the function as the returned value:
create or replace function f2(istr varchar)
returns text as $$
begin return(select 'hello! '::varchar || istr); end;
$$ language plpgsql;

Related

Why can't we call procedure from sql

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).

EXECUTE statement syntax error in PostgreSQL

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.

Performance impact of function calls in an SQL Query (About Context Switching)

Are there any performance impact in calling functions in an SQL statement due to context switching between SQL and PL/SQL engines? Or is the potential impact dependent on the function called?
Calling built-in functions:
select dbms_crypto.hash(utl_raw.cast_to_raw(COLUMN),1) from TABLE_NM;
Calling PL/SQL functions:
create or replace package PCK as
function doSomething(val varchar2) return varchar2;
end PCK;
select PCK.doSomething(COLUMN) from TABLE_NM
Are there performance overhead due to function calls? Thanks.
Calling built-in functions:
It depends. But, most of the native SQL functions and built-in functions are compiled in low-level "C language" as a single module in the Oracle kernel. For example, CASE or UPPER function won't have any context switch between the two engines as I said they are in a single module.
Well, there are some built-in functions which are exceptions, like SYSDATE and USER etc. Thomas Kyte has beautifully explained it here.
Calling PL/SQL functions
A SQL call in PL/SQL, or vice-versa, i.e. a PL/SQL call in SQL needs a context switch. There is a call overhead to go from SQL to PLSQL (the "hit" is most evident when SQL invokes PLSQL - not so much the other way, when SQL is embedded in PLSQL).

Difference between a function and a statement

In class we were asked to name several PL/SQL functions and state their use. Someone mentioned CREATE FUNCTION and I noted that Oracle labeled this as a statement and not a function.
I am unable to give a very good answer on the difference between the two. I am thinking that a statement is more of a declarative tool that specifies what the program is to accomplish whereas a function seems more procedural, we define the procedure for a new function in the CREATE FUNCTION statement.
The distinction seems clearer for something like a SELECT statement, can someone help with a clear delimitation between the two?
A statement is a piece of code that executes. It is a command. It does something. Example:
print "Hello World"
A function is a block of code that you call with parameters and it returns a value (even if that value is undefined). Example:
function(a) { return a * 2 }
The word "statement" has two different meanings in SQL and PL/SQL.
In a narrow technical sense, CREATE FUNCTION is a type of SQL statement, and CREATE FUNCTION contains PL/SQL statements.
In the more general sense, a SQL statement is declarative code that tells the database "what is true" or "what has to be done", without detailed instructions on "how to do it". A function, or any PL/SQL block, is imperative code that tells the database exactly "what to do". Declarative SQL is usually simpler and faster than imperative PL/SQL so it's usually best to do most of the work in SQL and just glue it together with PL/SQL.
SQL has about 170 commands (as defined by V$SQLCOMMAND), organized into about 31 statement types, organized into the below 6 categories. The CREATE FUNCTION command is a CREATE statement type in the DDL category. That classification scheme is not 100% clear from the database and manuals, but I've used it to thoroughly classify all SQL statements.
Data Definition Language (DDL) Statements
Data Manipulation Language (DML) Statements
Transaction Control Statements
Session Control Statements
System Control Statement
Embedded SQL Statements
In PL/SQL, most blocks are a sequence of statements. These statements could be an assignment, loop, fetch, block, etc.
To make things more confusing, in 12c a SQL statement can contain PL/SQL statements:
with function f return number is begin return 1; end; select f from dual;
CREATE FUNCTION is a statement. The function itself is a FUNCTION. Running the statement that creates the function allows you to access the function.
In general, if you're creating anything in the database, you are using a statement (in particular, a data-definition language (DDL) statement). The item you create, be it a table, function, package, etc., can then be referenced in future statements.

How to convert a big set of SQL queries into a single stored procedure that uses a variable?

I am trying to convert a big list of SQL statements into a PostgreSQL stored procedure that uses a variable, one that should be populated from the result of one SELECT.
If you want to see what has to be run, you can check it here
As far as I know PostgreSQL does not allow use to use variables inside stored procedures that are using SQL language, so I'm looking for solutions that would require a minimal number of changes.
It's much easier after you find the right syntax:
Here is the procedure definition for plpgsql language:
DECLARE myvar integer;
BEGIN
SELECT INTO myvar FROM ...;
-- use myvar
END;
The code seems to be pretty repetitive. Will EXECUTE be of any help? (manual about execute) (example and more information) It allows you to run predefined queries and create new ones on the fly.