Character/String passed from java to stored procedure does not work - sql

Hi I have a stored procedure which accepts parameter "Q_RES" from java. Its value is either "Y" or "N" . In my stored procedure I have a condition
If Q_RES = 'Y' THEN
sp_stat = 'TABLENAME.RES IN (' || Q_RES || ')';
END IF
nut I get error has ORA-00904: "Y" invalid Identifier
How can I fix this?

In PL/SQL assignment is Pascal style :=', not=`. Aside from that, I don't see any problem with the string concatenation shown here.
I suspect that sp_stat is being used later, in composing dynamic SQL. I would take a close look at the SQL being generated. It's probably goign to look like this:
... TABLENAME.RES IN (Y) ...
And if that is interpreted as SQL text, Oracle is going to see that bareword Y as an identifier, such as a column name, and attempt to resolve that. (If a table referenced in the query has a column named Y, the query wouldn't throw an error about an invalid identifier.
Just guessing here, but I suspect that we want Y to be a string literal. A string literal is enclosed in single quotes, like this:
... TABLENAME.RES IN ('Y') ...
To get a single quote inside a string literal, we can use two single quotes, e.g.
'I''m happy this is working'
Since we already know Q_RES is equal to 'Y', why not just do this:
sp_stat := 'TABLENAME.RES IN (''Y'')';
^^ ^^
or, if we want to reference Q_RES, enclose it in single quotes, like this:
sp_stat := 'TABLENAME.RES IN (''' || Q_RES || ''')';
^^ ^^

Related

Using LIKE pattern dynamically in execute format query in postgresql--9.5

I want to insert footext into LIKE pattern dynamically, but it gives error saying
ERROR: unrecognized conversion type specifier "'"........
This is my query:
RETURN QUERY EXECUTE format ('SELECT foocolumn
FROM footable
WHERE foocolumnother LIKE ''%L%'' ', footext);
Little late to the party, but according to Erwin's answer and the document, you can also try the ~ character of regex. So test out this
RETURN QUERY EXECUTE format ('SELECT foocolumn
FROM footable
WHERE foocolumnother ~ %L ', footext);
If you want to add a % into the format string you need to double it e.g. %F%%
%Lalso correctly adds single quotes so you don't need to put them in the format string.
However: using %F%% would generate 'bla'% - which is incorrect.
You need to add the wildcard to the variable not the format string:
RETURN QUERY EXECUTE format ('SELECT foocolumn
FROM footable
HERE foocolumnother LIKE %L' ', concat(footext, '%'));
Another late entry. Doubling both the single-quotes and percents works for me in Postgres 11.x:
l_query text := FORMAT('
SELECT e.gid, e.sessionname, e.shared, e.created, e.created_by
FROM exercise e
WHERE LOWER(e.created_by) LIKE ''%%%s%%'';'
, LOWER(p_user));
RETURN QUERY EXECUTE l_query;

ORACLE SQL IN Clause (SQL Query)

I'm having : delimited column like 1:2:3:. I want to get this into 1,2,3. My query looks like,
select name
from status where id IN (SELECT REPLACE(NEXT_LIST,':',',')
FROM status);
but I got an error
ORA-01722: invalid number
(1, 2, 3, 4) is different from ('1, 2, 3, 4'). IN requires the former, a list of values; you give it the latter, a string.
You have two options mainly:
Build the query dynamically, i.e. get the list first, then use this to build a query string.
Tokenize the string. This can be done with a custom pipelined function or a recursive query, maybe also via some XML functions. Google "Oracle tokenize string" to find a method that suits you.
UPDATE Option #3: Use LIKE as in ':1:2:3:4:' like '%:3:%'
(This requires your next_list to contain only simple numbers separated with colons. No leading zeros, no blanks, no other characters.)
select name
from status
where (select ':' || next_list || ':' from status) like '%:' || id || ':%'
i agreed with Thorsten but i wonder if we just replace one more time would it works? i mean like this:
select name
from status where id IN (SELECT replace(REPLACE(NEXT_LIST,':',','),'''','')
FROM status);
The REPLACE function returns a string, so the nested query returns a list of string values (where colons replaced with commas), but not a list of number values. When Oracle engine interprets id IN (str_value) it tries to cast the str_value to number and raises exception ORA-01722: invalid number because there are cases like '1:2:3' which are definetely unparseable.
The "pure sql" approach leads us to using custom function detecting if a number is in a colon-separated list:
-- you need Oracle 12c to use function in the WITH clause
-- on earlier versions just unwrap CASE statement and put it into query
WITH
FUNCTION in_list(p_id NUMBER, p_list VARCHAR2) RETURN NUMBER DETERMINISTIC IS
BEGIN
RETURN CASE WHEN
instr(':' || p_list || ':', ':' || p_id || ':') > 0
THEN 1 ELSE 0 END;
END;
SELECT *
FROM status
WHERE in_list(id, next_list) = 1;
Here I assume that values in the next_list column are strings containing numbers separated with colon without spaces. In common case you shall modify the function to match specific list formats.

MSAccess SQL Too few parameters. Expected 4

I'm using Delphi XE2 and AnyDAC and an MSAccess db.
The table 'timea' has 5 fields:
Rec_No AutoNumber
App text
User_ID text
PW text
Comment memo
This code throws the error below. The query works just fine in Access query designer.
sql := 'INSERT INTO [timea] (App, User_ID, PW, Comment) VALUES ("zoo", "Bill", "mi7", "Liger");';
adconnection1.ExecSQL(sql);
Project PWB.exe raised exception class EMSAccessNativeException with message '[AnyDAC][Phys][ODBC][Microsoft][ODBC Microsoft Access Driver] Too few parameters. Expected 4.'.
Both SQL and Delphi are using single quotes as string boundaries. Since you want to have singe quote inside the string, you have to "escape" it using doube single quote.
For example, if you write S := 'Guns''N''Roses' the varieble S will contain string Guns'N'Roses - 12 characters, not 14.
Be careful when you are concatenating string values, since they might contain single quotes, too. The recommended way to write the query in this case is, for example:
sql := 'INSERT INTO Table (Col) VALUES (' + QuotedStr(Val) + ')';
Function QuotedStr wll take care and double all single quotes in the string. This is also essential to avoid insertion hacks.

PL/SQL Use Parameters Contains Quotation Marks

I wrote a procedure that included parameters type varchar2 and i pass from my application string is like that "'O','H','Y'" and my query is below.
select * from table_name t where t.productname in (parameter)
Query does not return any data. How to handle it?
I try yo double or three quatitions marks.
Try to set the parameter like this 'O,H,Y'
Here you can see some examples
If you are trying to pass a procedure as parameter then you should get nothing or error. You can only pass a function that returns a value as we all know. You need to add your code and samples to help you more. What exactly are you passing in ()?
-- Correct syntax to pass parameters in your case --
select * from table_name t where t.productname in ('O', 'H', 'Y')
/
To pass single quotes in an sql query, use single quotes twice. Simple!
You can have:
select * from table_name t where t.productname in ('''O''', '''H''', '''Y''')
To test this, you can use:
SELECT 'Schindler''s List' AS fname FROM dual;
and see that you can easily pass single quotes to a query.
Double quotes are not much of matter here. We can directly use double quotes inside an SQL string literal, like
SELECT 'He said, "Give me my teddy bear!"' AS dilogue FROM dual;

simple parameter substitution in regexp_matches postgreSQL function

I have a table with a structure like this...
the_geom data
geom1 data1+3000||data2+1000||data3+222
geom2 data1+500||data2+900||data3+22232
I want to create a function that returns the records by user request.
Example: for data2, retrieve geom1,1000 and geom2, 900
Till now I created this function (see below) which works quite good but I am facing a parameter substitution problem... (you can see I am not able to substitute 'data2' for $1 in... BUT yes I can use $1 later
regexp_matches(t::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer
MY FUNCTION
create or replace function get_counts(taxa varchar(100))
returns setof record
as $$
SELECT t2.counter,t2.the_geom
FROM (
SELECT (regexp_matches(t.data::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer as counter,the_geom
from (select the_geom,data from simple_inpn2 where data ~ $1::text) as t
) t2
$$
language sql;
SELECT get_counts('data2') will work **but we should be able to make this substitution**:
regexp_matches(t::text, E'($1... instead of E'(data2....
I think its more a syntaxis issue, as the function execution gives no error, just interprets $1 as a string and gives no result.
thanks in advance,
A E'$1' is a string literal (using the escape string syntax) containing a dollar sign followed by a one. An unquoted $1 is the first parameter to your function. So this:
regexp_matches(t, E'($1[\+])([0-9]+)'))[2]::integer
as you've found, won't interpolate the $1 with the function's first parameter.
The regex is just a string, a string with an internal structure but still just a string. If you know that $1 will be a normal word then you could say:
regexp_matches(t, E'(' || $1 || E'[\+])([0-9]+)'))[2]::integer
to paste your strings together into a suitable regex. However, it is better to be a little paranoid, sooner or later someone is going to call your function with a string like 'ha ha (' so you should be prepared for it. The easiest way that I can think of to add an arbitrary string to a regex is to escape all the non-word characters:
-- Don't forget to escape the escaped escapes! Hence all the backslashes.
str := regexp_replace($1, E'(\\W)', E'\\\\\\1', 'g');
and then paste str into the regex as above:
regexp_matches(t, E'(' || str || E'[\+])([0-9]+)'))[2]::integer
or better, build the regex outside the regexp_matches to cut down on the nested parentheses:
re := E'(' || str || E'[\+])([0-9]+)';
-- ...
select regexp_matches(t, re)[2]::integer ...
PostgreSQL doesn't have Perl's \Q...\E and the (?q) metasyntax applies until the end of the regex so I can't think of any better way to paste an arbitrary string into the middle of a regex as a non-regex literal value than to escape everything and let PostgreSQL sort it out.
Using this technique, we can do things like:
=> do $$
declare
m text[];
s text;
r text;
begin
s = E'''{ha)?';
r = regexp_replace(s, E'(\\W)', E'\\\\\\1', 'g');
r = '(ha' || r || ')';
raise notice '%', r;
select regexp_matches(E'ha''{ha)?', r) into m;
raise notice '%', m[1];
end$$;
and get the expected
NOTICE: ha'{ha)?
output. But if you leave out the regexp_replace escaping step, you'll just get an
invalid regular expression: parentheses () not balanced
error.
As an aside, I don't think you need all that casting so I removed it. The regexes and escaping are noisy enough, there's no need to throw a bunch of colons into the mix. Also, I don't know what your standard_conforming_strings is set to or which version of PostgreSQL you're using so I've gone with E'' strings everywhere. You'll also want to switch your procedure to PL/pgSQL (language plpgsql) to make the escaping easier.