How to include ' in dynamic query? - dynamic

I need to generate a query like this
SELECT max(batch_sk) INTO ln_batch FROM test_app.table WHERE categ_cd = 'ABC' ;
This 'ABC' is coming as an input parameter in the procedure(in_code).
I have tried different version of the below mentioned query , but not getting the correct query .
SET lv_query ='SELECT max(batch_sk) INTO ln_batch FROM test_app.table
WHERE categ_cd = ''''||in_code||'';
How to include those ' in the query?

Several things wrong here.
Mismatched / un-escaped quotes
Concatenation operates on character strings and there is no implicit
conversion from TIMESTAMP to VARCHAR. You would need to convert with explicit CAST or TO_CHAR, etc. first
SELECT … INTO is not allowed as dynamic SQL. Perhaps parameterized static SQL with a host variable?
SELECT max(batch_sk) INTO ln_batch FROM test_app.table WHERE categ_cd=:in_code;
otherwise you need a dynamic cursor to supply the value as a literal
DECLARE lv_cur CURSOR for lv_stmt;
SET lv_query ='SELECT max(batch_sk) FROM test_app.table WHERE categ_cd = '''||in_code||'''';
PREPARE lv_stmt FROM lv_query;
OPEN lv_cur;
FETCH lv_cur INTO ln_batch;
CLOSE lv_cur;

Related

How to build dynamic query argument for external query?

I want to build dynamic query parameter based on declared variable for EXTERNAL_QUERY.
So I declare STRING variable via concatenation 2 strings:
DECLARE str STRING DEFAULT "SELECT * FROM public.stats WHERE import_date >= "||"'2021-11-29'";
Then trying to set this variable as argument into EXTERNAL_QUERY:
SELECT * FROM EXTERNAL_QUERY("dataset.location.conn_name", str);
It's returns an error:
Query error: Invalid table-valued function EXTERNAL_QUERY Connection argument in EXTERNAL_QUERY must be a literal string or query parameter
What I do wrong?
Not perfect, but works for me.
DECLARE str STRING DEFAULT '''"SELECT * FROM public.stats WHERE import_date >= "'''||"'2021-11-29'";
EXECUTE IMMEDIATE """
SELECT * FROM EXTERNAL_QUERY(\"dataset.location.conn_name\",?);
"""
USING str
Thanks #Timogavk for your answer, I spent a while looking for a solution.
Though in my case I had to change the DECLARE for something more like this, without the additional quotations for it to work (I was working on dynamically querying different tables):
DECLARE str STRING DEFAULT 'SELECT * FROM ' || <table_name> || ' Limit 10';

Using PostgreSQL parameters with booleans in EXECUTE / USING

i want to use parameters for my dynamic queries. I have a statements like so:
RETURN QUERY EXECUTE 'SELECT * FROM boards AS b WHERE b.slug = $1 AND $2'
USING filter_slug, parent_id_query;
I get a ERROR: argument of AND must be type boolean, not type text
if i do it like this:
RETURN QUERY EXECUTE 'SELECT * FROM boards AS b WHERE b.slug = ''' || filter_slug || ''' AND ' || parent_id_query;
it works though.
I feel like i am missing something / not understanding something. Please help.
What you are missing is how parameters are used. Parameters are not macros that replace arbitrary text inside a SQL statement. Instead, they are literal values assigned to "variables" inside the code. These values are typically numbers, strings, or dates.
In particular, parameters cannot be used for:
identifiers (columns names and table names)
function names
operators
SQL keywords
general expressions
So, unfortunately, you have to construct that part of the query without a generic parameter (although you can have $2 = $3)

Because the IN clause () SQL Server does not work this way

see if someone can get me this question:
This is my SQL query which loads into a temporary table for which to consult posterirormente there all goes well:
DECLARE #listStr VARCHAR(MAX)
SELECT #listStr = COALESCE(#listStr+' ,' , '') + sCodProducto
FROM dbo.Productos WHERE sCodProducto IN (80063, 80061, 80067, 80062, 80065)
INSERT INTO #IDPROD2(CODIGO)
SELECT #listStr
if I make this a select shows me the following data:
SELECT * FROM #IDPROD2
Well, now if I consult so this brings me nothing:
SELECT * FROM dbo.Productos P WHERE P.sCodProducto IN (SELECT CODIGO FROM #IDPROD2)
now if it works this way:
SELECT * FROM dbo.Productos P WHERE P.sCodProducto IN (80061 ,80062 ,80063 ,80065 ,80067)
A field in a query result is considered a single VALUE. The actual contents of that field are irrelevant. Doesn't matter if you have a numbers in CSV format, or one single number - that entire chunk of data is one single VALUE, as far as the DB is concerned.
Since it's a single value, your codigo field's contents are parsed/executed as:
... WHERE foo IN (#codigo)
... WHERE foo IN ('1,2,3,4,...');
... WHERE foo = '1,2,3,4,....';
The DB will NOT parse those values, and therefore will NOT treat string as multiple distinct values.
If you want the contents of a single field or variable to be treated as multiple distinct values, you have to use dynamic sql:
sql = "SELECT .... WHERE foo IN (" + #codigo + ")";
exec #sql;
Note that this is basically a form of SQL injection. You remove the "context" of being a single value from that variable field, and force the DB to treat it as multiple different values.
Some DBs get around this by providing extract functions, e.g. mysql's find_in_set, which is designed specifically for this:
SELECT ... WHERE FIND_IN_SET('80063', '80063, 80061, 80067, 80062, 80065');
There is no such function in TSQL, but can be simulated, even with a simple like query:
... WHERE foo='80063' OR foo LIKE '80063,%' OR foo LIKE '%,80063,%' OR foo LIKE '%,80063'

Converting Varchar to Datetime for Stored procedure input

I want to use a datetime parameter in a stored procedure, in T-SQL, that if NULL will revert to 12/31/9999.
My code looks like this:
EXEC abc.someStoredProc #i_param1, #i_param2, ISNULL(#l_Termination_date, '12/31/9999')
I get an error:
Incorrect syntax near '#l_Termination_date'
I've tried using convert and cast (for example:
ISNULL(#l_Termination_date,CAST('12/31/9999' AS datetime))
but can't seem to get it right. What am I doing wrong?
You can pass variables or literals as arguments to execute a stored procedure, (or call one of a few specific functions), but what you can't do is have arbitrary expressions.
Move it to a separate step:
SET #l_Termination_date = ISNULL(#l_Termination_date,'99991231')
EXEC abc.someStoredProc
#i_param1
, #i_param2
,#l_Termination_date
(Or use a separate variable if you don't want to overwrite #l_Termination_date)
DECLARE #l_Termination_date DATE ;
SET #l_Termination_date = ISNULL(#l_Termination_date,'12/31/9999')
EXEC dbo.USP_abc.someStoredProc (
#i_param1
, #i_param2
,#l_Termination_date )

Using LOCATE string function in stored procedure

Is anyone familiar with using the LOCATE with a passed in string varialbe? I am trying to use it to determine if there is a comma in a string that was set in the stored procedure but have not been able to get it to work properly. My code looks something like this
DECLARE string VARCHAR(10);
DECLARE comma_found INT;
SET string = 'hello, world';
SET comma_found = SELECT LOCATE(',',string);
IF( comma_found <> 0 ) THEN
...execute code....
END IF;
This code will not complie because of the SELECT LOCATE and I can not figure out what is wrong. Is it my syntax? Usage? Is there any other string maniuplation function I can use to accomplish this? I am doing this within a stored procedure in Mysql.
I haven't used MySQL in a long time so I'm not completely familiar with the newer syntax but from some googling, I believe
SET comma_found = SELECT LOCATE(',',string);
should be
SELECT #comma_found := LOCATE(',',string);
then you can use #comma_found eg:
SELECT #comma_found
It seems that you're trying to assign a data set to the variable rather than the result of the LOCATE
See here: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html
Well the syntax for LOCATE is LOCATE(substring, string). Your query literally says LOCATE(',', string) where string is a varchar(10). Your string is actually more than 10 characters long though =P