SET LANGUAGE in SQL-Prozedure - tsql

I have tried to use "SET LANGUAGE Italian" in MSSQL Procedure in order to get the month name on Italian.
However stored procedure after executing does not return the query result. In case SET LANGUAGE is not used, the query result is displayed as usually.
CREATE PROCEDURE language
AS
BEGIN
SET LANGUAGE Italian;
...
SET query ='SELECT ....'
EXEC (query)
END

because EXEC uses different context, just add set language inside : SET query = 'set language italian;SELECT ...'
you can also set the default language in the connexion user login properties

Related

PostgreSql SET configuration_parameter from Stored Procedure

I am implementing Row Level Security (RLS) on a postgres table. To use a single user, I am setting a configuaration_parameter for each session that maps to the row's identity and it works. I can test this using SQL but since I am using Mulesoft for the application, I don't have control over setting up connections and setting the parameter then. I tried to create a stored procedure where I try to set the value in the beginning but postgres doesn't like it. The docs don't share whether I can implement it in the SP or not so wondering if you guys know for sure so I can look at alternate solutions.
https://www.postgresql.org/docs/12/sql-set.html
The below does not work if I uncomment the line SET doc.provider=$1;
CREATE OR REPLACE PROCEDURE getParticipants(text)
LANGUAGE plpgsql
AS $$
BEGIN
--SET doc.provider=$1;
SELECT * FROM disclosure.participantsxref;
END;
$$;
Statement SET doesn't allow parametrization.Instead you can use a function set_config:
CREATE OR REPLACE FUNCTION foo(text)
RETURNS SETOF disclosure.participantsxref AS $$
BEGIN
PERFORM set_config('doc.provider', $1, true);
RETURN QUERY SELECT * FROM disclosure.participantsxref;
END $$
LANGUAGE plpgsql;
In your example, there is another issue - PostgreSQL's procedures cannot to returns tables - if you want to return table, then you have to use function. Functions can return tables with statement RETURN QUERY.
You can try to use dynamic SQL :
create or replace procedure myproc ()
as $$
begin
execute format('set lc_numeric=%L', 'fr_FR') ;
end;
$$
language 'plpgsql';
CREATE PROCEDURE
show lc_numeric;
lc_numeric
-------------
en_US.UTF-8
(1 row)
call myproc();
CALL
show lc_numeric;
lc_numeric
------------
fr_FR
(1 row)

PostgreSQL use of CurrentDatabase to set variable

I am trying to use below syntax to set variable under HDB DATABASE.
ALTER DATABASE HDB SET "abc.var1"='aaa';
However I need to provide database name for this. If I want to use CURRENT database instead.
There is a method in PostgreSQL which actually returns current database name: current_database(), but even below example is also not a valid one.
ALTER DATABASE current_database() SET "abc.var1"='aaa';
How can I achieve this ?
You need dynamic SQL for that:
do
$$
begin
execute format('alter database %I SET %I = %L', current_database(), 'abc.var1', 'aaa');
end;
$$
Using parameters and the placeholders %I and %L for the variable name and value avoids nesting quotes in the call to format() and properly deals with quoting.

How to return result set from PostgreSQL stored procedure?

PostgreSQL supports stored procedure (not function) since version 11. I created a stored procedure like this:
CREATE OR REPLACE PROCEDURE get_user_list ()
LANGUAGE SQL
SECURITY DEFINER
AS $$
SELECT "id",
"username",
"display_name"
FROM "user"
ORDER BY "created_at" ASC;
$$;
But when I am trying to execute this stored procedure, it does not return any data:
postgres=# CALL get_user_list();
CALL
postgres=# SELECT * FROM get_user_list();
ERROR: get_user_list() is a procedure
LINE 1: SELECT * FROM get_user_list();
^
HINT: To call a procedure, use CALL.
So the question is, how can a stored procedure returns its result set in PostgreSQL 11+?
Following the docs on Postgres 11 (bold emphasis mine):
A procedure does not have a return value. A procedure can therefore end without a RETURN statement. If a RETURN statement is desired to exit the code early, then NULL must be returned. Returning any other value will result in an error.
You could mark your parameters as output though, so that they would behave like variables.
On a side note there's normally a distinction within other DBMS that functions can only call SELECT statements and should not modify data while procedures should be handling the data manipulation and data definition languages (DML, DDL). This concludes (in my opinion) that creating a procedure to simply perform a stable (*) select statement is not the desired technique.
(*) Read more on function volatility here.
In case if you have one select in procedure to get result set you can create view like this:
CREATE OR REPLACE VIEW as get_user_list
SELECT "id",
"username",
"display_name"
FROM "user"
ORDER BY "created_at" ASC;
and then select * from get_user_list to get result set.

How to retrieve the search_path set for an function using a query on information_schema?

I have multiple functions for each schema that have search_path defined on the creation in this way:
CREATE OR REPLACE FUNCTION the_schema.update_complete_url(updateLang bigint) RETURNS boolean AS $$
DECLARE
tree_row record;
BEGIN
// body of function
END
$$ LANGUAGE plpgsql SET search_path=the_schema,public,pg_temp;
The search_path is defined so that I do not need to prefix each table in the function body with the_schema. which makes it easier for me to maintain those functions.
Now I have a maintaining/migration script that tests if certain functions exits and have the correct settings. Retrieving the function itself is not a problem as it would look that way:
SELECT * FROM "information_schema"."routines"
WHERE "routine_type"='FUNCTION' AND "specific_schema"='the_schema';
And querying for the parameters is also no problem using "information_schema"."parameters", but where is the SET search_path=the_schema,public,pg_temp part stored?
AFAIK it is not available in information_schema.
You can get it thru pg_catalog, but it is PostgreSQL specific:
select unnest(proconfig) from pg_proc where proname = 'function_name';

PostgreSQL execute statement conditionally by server version

I'm currently writing some installer script that fires SQL files against different database types depending on the system's configuration (the webapplication supports multiple database server like MySQL, MSSQL and PostgreSQL).
One of those types is PostgreSQL. I'm not fluent with it and I would like to know if it's possible to make a statement into a define/populate SQL file that makes an SQL query conditional to a specific PostgreSQL server version.
How to make an SQL statement conditionally in plain PGSQL so that it is only executed in version 9? The command is:
ALTER DATABASE dbname SET bytea_output='escape';
The version check is to compare the version with 9.
Postgres does have version() function, however there is no major_vesion(). Assuming that output string always includes version number as number(s).number(s).number(s) you could write your own wrapper as:
CREATE OR REPLACE FUNCTION major_version() RETURNS smallint
AS $BODY$
SELECT substring(version() from $$(\d+)\.\d+\.\d+$$)::smallint;
$BODY$ LANGUAGE SQL;
Example:
=> Select major_version();
major_version
---------------
9
(1 row)
However real issue here is that AFAIK you can't execute your commands conditionally in "pure" SQL and best what you can do is to write some stored function like this:
CREATE OR REPLACE FUNCTION conditionalInvoke() RETURNS void
AS $BODY$
BEGIN
IF major_version() = 9 THEN
ALTER DATABASE postgres SET bytea_output='escape';
END IF;
RETURN;
END;
$BODY$ LANGUAGE plpgsql;
I think that you should rather use some scripting language and generate appropriate SQL with it.
Or you could just use
select setting from pg_settings where name = 'server_version'
Or
select setting from pg_settings where name = 'server_version_num'
If you need major version only
select Substr(setting, 1, 1) from pg_settings where name = 'server_version_num'
or
select Substr(setting, 1, strpos(setting, '.')-1) from pg_settings where name = 'server_version'
if you want it to be compatible with two digit versions.
Maybe you could make things dependent on the output of
select version();
(probably you'll have to trim and substring that a bit)
BTW (some) DDL statements may not be issued from within functions; maybe you'll have to escape to shell-programming and here-documents.