Is there any way to write dynamic queries in Postgres' SQL dialect without using PL/pgSQL? - postgresql

I need to write dynamic query in Postgres which should not be a function/procedure.
I tried using Prepare and execute statement but, could not find any thing wherein i would generate a plain text and then execute.
SET #sql = 'SELECT #endDate = endDate from '+#metadbname+'.dbo.sometable where some condition';
EXECUTE sp_executesql #sql, some_variables
Can we have any variation of above query in PostgreSQL without using PL/pgSQL.

Related

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.

dynamic sql query in postgres

I was attempting to use Dynamic SQL to run some queries in postgres.
Example:
EXECUTE format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition)))
I have to query a table, which is of the form result_%s_table wherein, I need to substitute the correct table name (an id) from an another table.
I get the error ERROR: prepared statement "format" does not exist
Link: string substitution with query result postgresql
EXECUTE ... USING only works in PL/PgSQL - ie within functions or DO blocks written in the PL/PgSQL language. It does not work in plain SQL; the EXECUTE in plain SQL is completely different, for executing prepared statements. You cannot use dynamic SQL directly in PostgreSQL's SQL dialect.
Compare:
PL/PgSQL's EXECUTE ... USING; to
SQL's EXECUTE
See the 2nd last par in my prior answer.
In addition to not running except in PL/PgSQL your SQL statement is wrong, it won't do what you expect. If (select id from ids where condition = some_condition) returns say 42, the statement would fail if id is an integer. If it's cast to text you'd get:
EXECUTE format('SELECT * from result_%s_table', quote_ident('42'));
EXECUTE format('SELECT * from result_%s_table', '"42"');
EXECUTE 'SELECT * from result_"42"_table';
That's invalid. You actually want result_42_table or "result_42_table". You'd have to write something more like:
EXECUTE format('SELECT * from %s', quote_ident('result_'||(select id from ids where condition = some_condition)||'_table'))
... if you must use quote_ident.
CREATE OR REPLACE FUNCTION public.exec(
text)
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN QUERY EXECUTE $1 ;
END
$BODY$;
usage:
select * from exec('select now()') as t(dt timestamptz)
Try using
RETURN QUERY EXECUTE '<SQL Command>'
This will return data into form of table. You have to use this into stored function of PostgreSQL.
I have already created on full demonstration on custom filter and custom sorting using dynamic query of PostgreSQL.
Please visit this url:
http://www.dbrnd.com/2015/05/postgresql-dynamic-sql/
These all look more complicated than the OP's question. A different formatting should do the trick.. but it could absolutely the case that I don't understand.
From how I read OP's question, I think others in a similar situation may benefit from how I got it.
I am using Postgre on Redshift, and I ran into this issue and found a solution.
I was trying to create a dynamic query, putting in my own date.
date = dt.date(2018, 10, 30)
query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''
But, the query entirely ignores the condition when typing it this way.
However, if you use the percent sign (%), you can insert the date correctly.
One correct way to write the above statement is:
query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''
So, maybe this is helpful, or maybe it is not. I hope it helps at least one person in my situation!
Best wishes.
EXECUTE will work only on pl/pqsql environment.
instead of EXECUTE try with SELECT
SELECT format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition))
output would be the dynamic query.

Dynamic SQL with parameters, when parameter value has predefined operators inside

I have a situation in a T-SQL stored procedure, where in a dynamic SQL, the parameter/s, referencing other variables, whose value has single quotes and other predefined operators. The problem is T-SQL script fails, when such a condition exist.
Attached is a sample code, demonstrating such a situation.
Any Idea how to solve such a case?
DECLARE #TransVocObj XML,#xmlfragment XML,#SQL NVARCHAR(MAX)
SELECT #TransVocObj = '<TransactionVoucherViewModel><TransactionRows></TransactionRows></TransactionVoucherViewModel>'
DECLARE #Narration varchar(100)
SET #Narration ='AABBCC''DD''EEFF'-- #Narration ='AABBCCDDEEFF'
Select #xmlfragment=
'<TransactionRow>'+'<Description>'+#Narration +'</Description>'+'<DebitAmount>'+CONVERT(VARCHAR(30),500.00)+'</DebitAmount>'+'</TransactionRow>'
SET #SQL=N' SET #TransVocObj.modify(''insert '+ CONVERT(NVARCHAR(MAX),#xmlfragment)+' into (/TransactionVoucherViewModel/TransactionRows)[1] '') '
EXECUTE sp_executesql #SQL,N'#TransVocObj XML Output,#xmlfragment XML',#TransVocObj OUTPUT,#xmlfragment
SELECT T.Item.query('.//Description').value('.','VARCHAR(60)') FROM #TransVocObj.nodes('//TransactionRows/TransactionRow') AS T(Item)
The database server is MS SQL SERVER 2005
You can double-up your single-quote characters within #Narration using the REPLACE function. So, when you build #xmlfragment it can look like:
Select #xmlfragment=
'<TransactionRow>'+'<Description>'+REPLACE(#Narration,'''','''''')+'</Description>'+'<DebitAmount>'+CONVERT(VARCHAR(30),500.00)+'</DebitAmount>'+'</TransactionRow>'

How to execute an SQL string in DB2

How do I execute an SQL string statement in DB2? I'm using IBM Data Studio.
Do you mean executing a dynamic SQL string? Something like:
DECLARE stmt VARCHAR(1000);
DECLARE my_table VARCHAR(50);
SET my_table = 'DEPT_'||deptNumber;
SET stmt = 'SELECT * FROM '||my_table;
PREPARE s1 FROM stmt;
EXECUTE s1;
You can only do that in a stored proc though. One defined as CREATE PROCEDURE GetDeptInfo (deptNumber VARCHAR(5)) for this example. Read about EXECUTE and PREPARE in the db2 docs http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp
After days of researching I found how to write and run dynamic SQL on DB2:
create or replace procedure Search ()
BEGIN
DECLARE v_dynamicSql varchar(2000);
SET v_dynamicSql = 'INSERT INTO dictonary(name) values(' || 'dynamicSQL in db2' ||')';
EXECUTE IMMEDIATE v_dynamicSql;
END;
Hope to help someone.
What difficulty are you encountering?
There are likely lots of ways to do it. Here's one:
File -> New -> Other -> SQL or XQuery script
You may need to create a project or define a database connection.
Enter the SQL code.
Script -> Run script.
Results will show up at the bottom of your screen.
In Control Center, right click the database, you will see "Query". Click on it and you are good to go.

T-SQL Table name alias

In my T-SQL script, I refer to same long table name several times. I use this query on different tables.
Is there a way to refer a table name by variable? If so, I can simple declare one variable at the top which script will use and just by setting value, I can run it on various tables without making changes in the script.
A couple of options.
Within a single SQL statement you can alias table names like so:
SELECT *
FROM MySuperLongTableName T
WHERE T.SomeField=1
If you need to do this over lots of statements across several scripts a synonym might be a better option:
CREATE SYNONYM SuperT FOR dbo.MySuperLongTableName
You could create a synonym for that table but obviously you'd need to make sure that nobody changed the definition of the synonym whilst the script was running (and no parallel invocations of the script)
Are you running these in SSMS? If so you could set SQL CMD mode (on the "Query" menu) and use
:setvar tablename "spt_values"
use master
select * from $(tablename)
You could do this as such:
Declare #TableName As nvarchar(max)
Declare #SQL AS nvarchar(max)
#TableName = 'longtablename'
#SQL = 'Select * From ' + #TableName
EXEC(#SQL)