In Oracle SQL, what would code like this be used for? - sql

Just studying some code , and came across this line:
v_VLDT_TOKEN_VLU := v_onl_acctID || ‘|’ || p_onl_external_id || ‘|’ || p_validation_target
It's a "validation token value" , but why would you concatenate the pipe symbol? I understand this is for dynamic SQL.

Here Pipe symbol is used as a delimiter/separator between the fields:
Assume,
v_onl_acctID = 123
p_onl_external_id = abc
p_validation_target = xyz
then
v_VLDT_TOKEN_VLU := v_onl_acctID || ‘|’ || p_onl_external_id || ‘|’ || p_validation_target
will evaluate to
v_VLDT_TOKEN_VLU = 123|abc|xyz
It is just another character for delimiter purpose and can be replaced with any other delimiter too. For reference, if the | is replaced by *, say
v_VLDT_TOKEN_VLU := v_onl_acctID || ‘*’ || p_onl_external_id || ‘*’ || p_validation_target
then the expression's value would be 123*abc*xyz
Note: || is used for concatenation

Looks like the pipe symbol is being used as a delimiter between the three fields.

I have actually seen similar code, but it was used to generate a unix statement that piped (|) the output of one command to another. If I remember correctly, they had a table with all of our database hosts, and oracle data directories. They used code similar to this to shell over to the specific database host, get a directory of the datafiles and write the output to a logfile back on the parent server which they then read in to update disk usage for reporting. This was years ago so I'm sure there is a better way to do it now.

Comment = answer apparently.
v_vldt_token_vlu looks like it's built up of three fields, with a pipe between each of them...I assume the pipe is built into the token_vlu field and then being compared to the same fields concatonated together here. Pipe was probably a developers preference. No real reference to dynamic SQL here

Related

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

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 || ''')';
^^ ^^

What is the line continuation character for HANA SQL?

What is the line-continuation character for HANA SQL? Considering I have a super long statement and want it to span across multiple lines instead of it being a super long one in a line.
Thanks.
For most SQL statements, you can implicitly continue on the next line. There is no "line-continuation character". Long strings can be continued on the next line by separating them in multiple strings concatenated with ||.
For example, this is perfectly valid HANA SQL:
SELECT
"RefID",
"FirstName",
"LastName"
FROM
"People"
WHERE
"FirstName" = 'Hubert Blaine'
AND
"LastName" = 'Wolfeschlegelsteinhausenbergerdorffvoralternwaren' ||
'gewissenhaftschaferswesenchafewarenwholgepflegeun' ||
'dsorgfaltigkeitbeschutzenvonangereifenduchihrraub' ||
'giriigfeindewelchevorralternzwolftausendjahresvor' ||
'andieerscheinenbanderersteerdeemmeshedrraumschiff' ||
'gebrauchlichtalsseinursprungvonkraftgestartseinla' ||
'ngefahrthinzwischensternartigraumaufdersuchenachd' ||
'iesternwelshegehabtbewohnbarplanetenkreisedrehens' ||
'ichundwohinderneurassevanverstandigmenshlichkeitt' ||
'konntevortpflanzenundsicherfreunanlebenslamdlichf' ||
'reudeundruhemitnichteinfurchtvorangreifenvonander' ||
'erintlligentgeschopfsvonhinzwischensternartigraum';
PS: That person actually exists. :)
You can hit the return key and have a statement split in multiple line for your convenience.
Like in the image below:
Even in dynamic SQL you can split the string (with the || operator) you're going to feed in the EXEC() command.

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.

Oracle SQL - Is there a better way to concatenate multiple strings with a given delimiter?

First question, so apologies in advance if this is stupid or unoriginal, but I've searched for about 30 mins now without finding any mention anywhere of my exact question:
Is there a way to concatenate a series of strings, to be separated by a given delimiter, without manually putting the delimiter between each column being concatenated?
To give a concrete example, I currently have this:
SELECT member_no as Member#,
(member_gname
|| ' '
|| member_fname) as Name,
(member_street
|| ' '
|| member_city
|| ' '
|| member_state
|| ' '
|| member_postcode) AS Address,
member_phone AS Phone,
TO_CHAR(member_joindate, 'dd-Mon-yyyy') as Joined
FROM MEMBER;
It works fine, and produces exactly the output I wanted, but as this is for study I'm less concerned about the output and more concerned with the readability and 'best practise' factors of the .sql file itself. I understand that CONCAT() only takes two arguments, so that won't work without nesting them (which is even uglier and less readable). I'm coming in totally naively here, but I was hoping there'd be some kind of magical AWESOMECONCAT() type of function that would take all the columns i need, as well as allowing me to specify what character I want separating them (in this case, a space). Any ideas?
Also, this is a separate question not worthy of posting by itself, but is there any way to select a column 'AS' and give it a name including whitespace? E.g 'Member #' would look better imo, and 'Join Date' would be clearer, but I've tried both brackets and single quotes after the AS and neither seems to fly with SQL developer.
We can still write our own AWESOMECONCAT(). Unfortunately, Oracle has no in built function. As the concatenate operator does the basic thing.
Using double quotes in the alias, you can make the column references case sensitive and even accept blanks. But note that, any more references to that column/expression needs double quotes with same text.
SELECT member_no as "Member #",
(member_gname
|| ' '
|| member_fname) as Name,
(member_street
|| ' '
|| member_city
|| ' '
|| member_state
|| ' '
|| member_postcode) AS Address,
member_phone AS Phone,
TO_CHAR(member_joindate, 'dd-Mon-yyyy') as "Join Date"
FROM MEMBER;
Is there a way to concatenate a series of strings, to be separated by a given delimiter, without manually putting the delimiter between each column being concatenated?
The best way to do concatenation from 11g onwards is the new string literal technique q'[]'.
For example :
select q'[This is a string, 'this is also a string'.]' from dual

What does symbol '||' mean in query

I have the following criteria api query before populating parametrs
where lower(generatedAlias7.personGivenName || :param6 || generatedAlias7.personSurName) like :param7)
Can anyone explain what does it mean ?
Some vendors (e.g. Oracle or PostgreSQL I think) offer the double bar || operator to concatenate strings.