psql passing parameter to sql script - postgresql

psql version 9.2, server version 12.0.
Trying to pass parameter to sql script ,
Executing the script and passing parameter :
psql --echo-queries -v ON_ERROR_STOP=0 -v TEST=100 postgresql://${curr_connection}<< EOF 1 > ${log_file} 2>&1
\timing
\i sql_script.sql
EOF
Please note I confirm script is working with no issue when using hardcoded value(without the parameter) ,
I guess it may relate that the parameter inside a quote or somthing,
sql_script.sql
INSERT INTO ACT_HI_COMMENT (action_,full_msg_,id_,message_,proc_inst_id_,task_id_,time_,type_,user_id_)
SELECT * FROM DBLINK ('host= MYHOST user=MYUSER password = MYPASS dbname=MYDB port=6432',
'SELECT ACT_HI_COMMENT.message_,ACT_HI_COMMENT.proc_inst_id_ FROM ACT_HI_COMMENT
where ACT_HI_COMMENT.TASK_ID_ in (Select distinct CBAN_A.TASK_ID_ from CBAN_OSS_ACT_RU_VARIABLE_TASK
where CBAN_OSS_ACT_RU_VARIABLE_TASK.GROUP_ID = :TEST )')
AS LINKTABLE (proc_inst_id_ character varying,task_id_ character varying,time_ timestamp without time zone,type_ character varying,
user_id_ character varying);
Getting error:
psql:/infadmin/inf/sql_script.sql:2: ERROR: syntax error at or near ":"
CONTEXT: while executing query on unnamed dblink connection
I tried also a single quotes around it as :'TEST'
INSERT INTO ACT_HI_COMMENT (action_,full_msg_,id_,message_,proc_inst_id_,task_id_,time_,type_,user_id_)
SELECT * FROM DBLINK ('host= MYHOST user=MYUSER password = MYPASS dbname=MYDB port=6432',
'SELECT ACT_HI_COMMENT.message_,ACT_HI_COMMENT.proc_inst_id_ FROM ACT_HI_COMMENT
where ACT_HI_COMMENT.TASK_ID_ in
(Select distinct CBAN_A.TASK_ID_ from CBAN_OSS_ACT_RU_VARIABLE_TASK
where CBAN_OSS_ACT_RU_VARIABLE_TASK.GROUP_ID = :'TEST' )')
AS LINKTABLE (proc_inst_id_ character varying,task_id_ character varying,time_ timestamp without time zone,type_ character varying,user_id_ character varying);
Getting error:
psql:/infadmin/inf/sql_script.sql:2: ERROR: syntax error at or near "TEST"
LINE 2: ... where CBAN_OSS_ACT_RU_VARIABLE_TASK.GROUP_ID = :'TEST' ..

As suspect , it didnt worked as the parameter is inside the single quotes,
I solved it by spliting the whole string inside the quotes into 2 ,
by
' first_part '|| :'TEST'||' <second_part>'
So sql looks like
INSERT INTO ACT_HI_COMMENT (action_,full_msg_,id_,message_,proc_inst_id_,task_id_,time_,type_,user_id_)
SELECT * FROM DBLINK ('host= MYHOST user=MYUSER password = MYPASS dbname=MYDB port=6432',
'SELECT ACT_HI_COMMENT.message_,ACT_HI_COMMENT.proc_inst_id_ FROM ACT_HI_COMMENT
where ACT_HI_COMMENT.TASK_ID_ in
(Select distinct CBAN_A.TASK_ID_ from CBAN_OSS_ACT_RU_VARIABLE_TASK
where CBAN_OSS_ACT_RU_VARIABLE_TASK.GROUP_ID = '|| :'TEST'||' )')
AS LINKTABLE (proc_inst_id_ character varying,task_id_ character varying,time_ timestamp without time zone,type_ character varying,user_id_ character varying);
``

Related

How to Perform Insert Operation with DbLink in Postgres

I am tying to perform insert with dblink in postgres but it is throwing error
column "Test" does not exist
Select *
from dblink('host=localhost user=postgres password=Test dbname=wb',
'Insert Into tblProducts(AccountNumber,AccountProductNumber,supplierproductnumber)
Values( 2012, 2022,'Test') Returning ProductNumber'
) AS tblProducts(ProductNumber integer)
You have to escape the quotes within the payload, using an additional quote '' (two single quotes):
Select *
from dblink('host=localhost user=postgres password=Test dbname=wb',
'Insert Into tblProducts(AccountNumber,AccountProductNumber,supplierproductnumber)
Values( 2012, 2022,''Test'') Returning ProductNumber'
) AS tblProducts(ProductNumber integer);

dblink returns SQL Error [42703]: ERROR: column "xy" does not exist

Can someone tell me why i get this error and how i can solve it?
I have a function like this:
CREATE OR REPLACE FUNCTION custom.dblink_function_v21()
RETURNS TABLE(name character varying, service character varying, scopes character varying)
LANGUAGE plpgsql
AS $function$
DECLARE
var_req TEXT;
rec_key record;
cur_key CURSOR FOR Select * from dblink(
'host=server1
user=user1
password=pw1
dbname=db1
port=5433',
'
select s.id,s.name,s.host from servers s where s.id IN (465,325) order by s.name
') as (srv character varying,name character varying, host character varying);
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req := 'Select * from dblink(
''host=' || rec_key.host || '
user=user2
password=pw2
dbname=db2'',
''
select
' || rec_key.name || ' as name ,
es.name as service,
es.scopes::varchar as scopes
from services es
'') as (srv varchar,service varchar,scopes varchar);
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
when i call it with select * from custom.dblink_function_v21() i get this error :
SQL Error [42703]: ERROR: column "dba01" does not exist
Where: Error occurred on dblink connection named "unnamed": could not execute query.
PL/pgSQL function custom.dblink_function_v21() line 43 at RETURN QUERY
dba01 is not a column.. it's my first value in column name.
If i just change the ' || rec_key.name || ' too ' || rec_key.srv || ' i suddenly works. But i don't want the id of the server in return i want the name. They both have same datatype and everything so i don't whats the Problem.
Ive been trying different things like crazy but nothing works..
Working with postgres v.10
This is the select statement you create:
select XXX as name , es.name as service, es.scopes::varchar as scopes from services es
where XXX is the value of rec_key.name - and the value of rec_key.srv in the latter case.
In the former case, the statement evaluates to:
select dba01 as name , es.name as service, es.scopes::varchar as scopes from services es
but in the latter case:
select 100 as name , es.name as service, es.scopes::varchar as scopes from services es
In the former case, the error is issued as the column dba01 does not exist. In the latter case, the number 100 is selected as name. It is a perfectly valid statement as it is not interpreted as a column name.
If you want to select the text value "dba01" as column "name" you can change that part to:
''' || rec_key.name || '''::text as name ,
Best regards, Bjarni

Using a variable in a function with sql and sh script

I am developing a set of .sql scripts which will be called by a .sh script. In this .sh script, I use the command:
psql "connection parameters" -f ./myscript.sql -v var1 = "schema.table"
For the moment everything is well.
In my .sql script, I currently have this:
CREATE or replace FUNCTION myFunction (tarteenpion varchar) RETURNS void AS $$
DECLARED
MONTH_MM varchar: = to_char (current_timestamp, 'MM');
YEAR_AAAA varchar: = to_char (current_timestamp, 'YYYY');
YEAR_AA varchar: = to_char (current_timestamp, 'YY')
cmd varchar: = 'DROP TABLE IF EXISTS' || tarteenpion || ';' ;
BEGIN
execute cmd;
END;
$$ LANGUAGE plpgsql;
--SELECT myFunction ('schema.table');
SELECT myFunction (: var1);
DROP FUNCTION myFunction (tarteenpion varchar);
My problem comes from the use of my external variable :var1
- If I directly write my value 'schema.table' with ', the function runs correctly. But I don't want that.
If I write my variable :var1 WITHOUT the ' I have this error
SELECT myFunction (: var1); => ERROR: missing FROM-clause entry for table "schema"
LINE 1: SELECT myFunction (schema.table);
So it is interpreted as not usable by the function.
If I write my variable ':var1' WITH the ' I have this error
SELECT myFunction (':var1'); => ERROR: syntax error at or near ":"
LINE 1: DROP TABLE IF EXISTS :var1
So it is not interpreted but used by the function.
Can you guide me to find a solution that has bothered me for a long time.
Thank you :)
You can make psql quote the variable value with single quotes:
SELECT myFunction (:'var1');
That will be replaced to
SELECT myFunction ('schema.table');

Dblink is not accepting the date format of postgressql

I am extracting the data from other databases by using dblink but when i put the date condition it is showing below error
ERROR: syntax error at or near "2019"
LINE 5: where date(l.create_date)='2019-01-01'')
^
SQL state: 42601
Character: 562
select cus.* into cus_details from dblink('dbname=dbname user=admin password=admin123',
'select l.id,l.create_date,l.write_date,b.campaign
from rb_lead l
left join rb_campaign b on l.team=b.id
where date(l.create_date)='2019-01-01'')
as cus (id integer,create_date timestamp without time zone,write_date timestamp without time zone,campaign integer)
There are quotes inside your quoted string.
select cus.* into cus_details
from dblink(
'dbname=dbname user=admin password=admin123',
'select ... where date(l.create_date)='2019-01-01''
)
^
You'll need to escape the quotes around 2019-01-01 by doubling them.
select cus.* into cus_details
from dblink(
'dbname=dbname user=admin password=admin123',
'select ... where date(l.create_date)=''2019-01-01'''
)

In SSMS copied string has different behaviour to original string

I am attempting to semi automate creation of my databases
As part of this I want to add extended properties of column descriptions.
When I try to run sp_sqlexec in my script ( or even just Exec(#mystring) I get an error. However, if while debugging, I copy the dynamic sql string from the watch window and then run sp_sqlexec on the copied string in a seperate window I get no errors and the extended properties are added correctly.
The following script demonstrates the problem:
--Create a table to apply column descriptions to
Create table dbo.table1 (id int, name nvarchar(20));
--Create the table that contains our column descriptions
Create table dbo.column_descs_table (schemaname nvarchar(20), tablename nvarchar(20), columnname nvarchar(20), column_description nvarchar(20))
Insert into column_descs_table (schemaname, tablename, columnname, column_description)
values ('dbo', 'table1', 'id', 'the id column'), ('dbo' , 'table1', 'name', 'the name column');
--Dynamic sql string varaible to hold the commands
Declare #dyn_sql nvarchar(max);
Set #dyn_sql = 'N'''; --Set to opening quote
--now create the string containing commands to add column escriptions
SELECT #dyn_sql = #dyn_sql + N' EXEC sp_addextendedproperty ''''Col Desc'''', ''''' + column_description + N''''', ''''SCHEMA'''', ' + schemaname + N', ''''TABLE'''', ' + tablename + N', ''''COLUMN'''', ' + columnname + N' ;'
FROM dbo.column_descs_table
Set #dyn_sql = #dyn_sql + ''''; --add the closing quote
Print #dyn_sql --If I copy the contents of #dyn_sql here and run seperately it works OK
Exec sp_sqlexec #dyn_sql -- this line causes error
The error I get is
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ' EXEC sp_addextendedproperty 'Col Desc', 'the id column', 'SCHEMA', dbo, 'TABLE', table1, 'COLUMN', id ; EXEC sp_addextendedprope'.
Yet if I step through the code and copy the contents of #dyn_sql then paste this as follows:
Exec sp_sqlexec N' EXEC sp_addextendedproperty ''Col Desc'', ''the id column'', ''SCHEMA'', dbo, ''TABLE'', table1, ''COLUMN'', id ; EXEC sp_addextendedproperty ''Col Desc'', ''the name column'', ''SCHEMA'', dbo, ''TABLE'', table1, ''COLUMN'', name ;'
Then the above works fine and the column descriptions are added as expected.
Any help on this specific copying problem is much appreciated. I do understand the security issues with dynamic sql ( this script will be removed from the database once my setup is complete)
Thanks in advance
Jude
It looks like it's because your leading N is included within the string to execute; you don't need it at all. In other words, you are ending up with something like this:
exec sp_execsql 'N'' exec sp_addextendedproperty /* etc. */ '''
But it should be like this:
exec sp_execsql N'exec sp_addextendedproperty /* etc. */ '
But why are you even using dynamic SQL here? All values passed to sp_addextendedproperty can be passed as parameters so there is no obvious reason to use dynamic SQL, unless you've simplified something for the question.
Finally, you should be using sp_executesql, it's the preferred way to execute dynamic SQL.
I believe that I have resolved my string copying problem. SQL was detecting double quotes in by concatenated string as empty strings and removing them. A simple example showing the problem and my solution is below:
--Example to Select 'simple string' and then 'concat string' into results sets
DECLARE
#Simplestring nvarchar( max ) = '' ,
#Concatstring nvarchar( max ) = '' ,
#Stringvar nvarchar( 10 ) = 'string';
--The double quotes in next line are the quotemark we want plus a quotemark acting
--as an escape character
--#simplestring will be set to 'Select 'simple string' '
SET #Simplestring = 'Select ''simple string'' ';
--Similarly we need #concatstring to be set to 'Select 'Concat string' '
SET #Concatstring = 'Select '' concat' + #Stringvar + ''; -- this wont work the last
--double quote will be removed
--Add a character that cannot appear in any othe part of the concatenation - I've used *
SET #Concatstring = 'Select '' Concat ' + #Stringvar + '*';
--Now replace the * with a quote mark
SET #Concatstring = REPLACE( #Concatstring , '*' , '''' ); -- This will work
EXEC sp_executesql #Simplestring;
EXEC sp_executesql #Concatstring;
There may be a simpler solution than mine.
Many thanks for the advice on using sp_executesql. I am working on changing my code to use this ( with variables passed in as parametrs).
Jude