In Oracle SQL, what is a single pipe character ( '|' ) used for? - sql

I was studying some dynamic SQL(or perhaps it was regular SQL ?) today in Oracle, when I saw the pipe char being used in a line like this:
someVar := 'someValue' | 'someOtherValue'
This puzzled me. Is it BITWISE-OR like in TSQL ? Or is it something else? I am aware of the concatenation operator ( || ) , but it wasn't that one.

The documentation only shows it as a bitwise OR operator in TimesTen:
Bitwise OR of the two operands.
Sets a bit to 1 if one or both of the corresponding bits in Expression1 and Expression2 are 1. Sets a bit to 0 if both of the corresponding bits are 0.
But you didn't mention TimesTen, and it isn't valid in 'normal' SQL or PL/SQL.

The || operator is used for concatenating two strings, in Oracle a single | is not a valid operator. Are you sure that the posted code actually works, and that is indeed running on an Oracle database?

Related

What is the purpose of the double tilde (~~) symbol in the below query?

This is the first table:
Line_Card
0-17
0-10
1-1
0-11
1-1-17
1-1-10
1-1-13
1-1-6
1-1-21
This is the second table:
Port
0-13-37
1-1-2-40
0-8-29
1-1-4-12
1-1-2-14
0-1-30
0-17-25
1-1-17-62
1-1-1-55
The below query is supposed to read from the product of the joined tables:
SELECT Line_Card, Port
FROM Table_1
LEFT JOIN Table_2 ON
Table_1.Column= Table_2.Column
AND Table_1.Port ~~ LIKE_ESCAPE((Table_2.Line_Card || '-%'),'\')
AND Table_1.Port !~~ LIKE_ESCAPE((Table_2.Line_card || '-%-%'),'\');
However, it shows an invalid SQL character error on oracle. It would be greatly appreciated if someone could also give me the equivalent of this statement or the infinity symbol in Teradata.
I am working through someone else's code and my understanding that this is oracle and that ~ has a purpose in oracle. The thing is that I can not find any reference to the double infinity ~~ symbol.
That's because it doesn't have any meaning in Oracle. It looks like this code is from PostgreSQL, where - as this answer says:
The operator ~~ is equivalent to LIKE, and ~~* corresponds to ILIKE. There are also !~~ and !~~* operators that represent NOT LIKE and NOT ILIKE, respectively. All of these operators are PostgreSQL-specific.
Even in PostgreSQL that implies you can just replace them with the LIKE and NOT LIKE equivalents; and that would work in Oracle too:
AND Table_1.Port LIKE Table_2.Line_Card || '-%'
AND Table_1.Port NOT LIKE Table_2.Line_card || '-%-%'
It appears that the LIKE_ESCAPE() part is a bespoke function that escapes wildcard characters. Given your sample data that doesn't seem necessary here.
db<>fiddle

Is there an equivalent to concat_ws in oracle?

I have a ton of columns I am trying to aggregate together and most of them have NULL values. I want to separate values that do appear with a ';' but I cannot find an effective way to do this in oracle. CONCAT_WS would be exactly what I need as it would not add the delimeter between NULL values, but oracle does not support this.
concat_ws(';','dx89','dx90','dx91','dx92') as diagnoses3
ORA-00904: "CONCAT_WS": invalid identifier
Using a function like this is similar but doesn't quite get me what I need as you can see the ';' on the end of the string since dx91 and dx92 are NULL values:
dx89||';'||dx90||';'||dx91||';'||dx92 as diagnoses2
I63.8;I63.9;;
Any help would be greatly appreciated!
You can use NVL2() function specific to Oracle DB together with pipe concatenation operators :
SELECT TRIM(LEADING ';'
FROM dx89||NVL2(dx90,';'||dx90,dx90)||
NVL2(dx91,';'||dx91,dx91)||
NVL2(dx92,';'||dx92,dx92)) AS "Concatenated String"
FROM t
Demo

Why "=" and "like" work in the same statement

I was practicing SQL injection skill, and I found that I could put = and LIKE in a single statement.
However, I'm not sure what does this mean and why it works?
SELECT 1 FROM users WHERE name='' LIKE '%'
So, what does that mean when I put = and LIKE in a statement, and when would I write something like this?
I am guessing that you are using MySQL, because this is syntactically correct in MySQL. It treats boolean types as numbers (which will be converted to integers and strings).
So, your code should be parsed as:
WHERE (name = '') LIKE '%'
This is because = and LIKE have the same precedence, and when operators have the same precedence, they are evaluated left-to-right (as explained in the documentation).
This, in turn evaluates to one of these three possibilities:
WHERE 1 LIKE '%' -- when name = ''
WHERE 0 LIKE '%' -- otherwise when name is not null
WHERE NULL like '%'
The first two will always evaluate to true. The third would discard any row where name is null.
(in MySQL and other popular DBMS) The LIKE operator is used to search for a specified pattern in a column. It admits "%" as a wildcard that represents zero, one, or multiple characters.
Your query always passes because the string '' meets this wildcard (zero characters). Incidentally, almost anything will. Some DBMS will react differently to such a query though.

Find phone numbers with unexpected characters using SQL

I posted the same question below for SQL in Oracle here and was provided the SQL info within that works.
However, I now need to perform the same in a DB2 database and if I attempt to run the same SQL it errors out.
I need to find rows where the phone number field contains unexpected characters.
Most of the values in this field look like:
123456-7890
This is expected. However, we are also seeing character values in this field such as * and #.
I want to find all rows where these unexpected character values exist.
Expected:
Numbers are expected
Hyphen with numbers is expected (hyphen alone is not)
NULL is expected
Empty is expected
This SQL works in Oracle:
...
WHERE regexp_like(phone_num, '[^ 0123456789-]|^-|-$')
When using the same SQL above in DB2, the statement errors out.
I found it easiest to answer your question by phrasing a regex which matches the positive cases. Then, we can just use NOT to find the negative cases. DB2 supports a REGEXP_LIKE function:
SELECT *
FROM yourTable
WHERE
NOT REGEXP_LIKE(phone_num, '^[0-9]+(-?[0-9]+)*$') AND
COALESCE(phone_num, '') <> '';
Here is a demo of the regex:
Demo
For newer version of db2, regexp is the way to go. If you are on an older version (perhaps why you get an error), you can replace all accepted chars with '' and check if the result is an empty string. Can't check right now, but from memory, it would be
WHERE TRANSLATE(phone_num, '', '0123456789-')<>''
EDIT:
For what it's worth your regexp works for V11 so you probably have an older version of Db2. Example of translate and regexp side by side:
]$ db2 "with t(s) as ( values '123456-7890', '12345*-7890' )
select s, 'regexp' as method from t
where regexp_like(s, '[^ 0123456789-]|^-|-$')
union all
select s, 'translate' as method
from t where TRANSLATE(s, '', '0123456789-')<>''"
S METHOD
----------- ---------
12345*-7890 translate
12345*-7890 regexp
2 record(s) selected.

Use '=' or LIKE to compare strings in SQL?

There's the (almost religious) discussion, if you should use LIKE or '=' to compare strings in SQL statements.
Are there reasons to use LIKE?
Are there reasons to use '='?
Performance? Readability?
LIKE and the equality operator have different purposes, they don't do the same thing:
= is much faster, whereas LIKE can interpret wildcards. Use = wherever you can and LIKE wherever you must.
SELECT * FROM user WHERE login LIKE 'Test%';
Sample matches:
TestUser1
TestUser2
TestU
Test
To see the performance difference, try this:
SELECT count(*)
FROM master..sysobjects as A
JOIN tempdb..sysobjects as B
on A.name = B.name
SELECT count(*)
FROM master..sysobjects as A
JOIN tempdb..sysobjects as B
on A.name LIKE B.name
Comparing strings with '=' is much faster.
In my small experience:
"=" for Exact Matches.
"LIKE" for Partial Matches.
There's a couple of other tricks that Postgres offers for string matching (if that happens to be your DB):
ILIKE, which is a case insensitive LIKE match:
select * from people where name ilike 'JOHN'
Matches:
John
john
JOHN
And if you want to get really mad you can use regular expressions:
select * from people where name ~ 'John.*'
Matches:
John
Johnathon
Johnny
Just as a heads up, the '=' operator will pad strings with spaces in Transact-SQL. So 'abc' = 'abc ' will return true; 'abc' LIKE 'abc ' will return false. In most cases '=' will be correct, but in a recent case of mine it was not.
So while '=' is faster, LIKE might more explicitly state your intentions.
http://support.microsoft.com/kb/316626
For pattern matching use LIKE. For exact match =.
LIKE is used for pattern matching and = is used for equality test (as defined by the COLLATION in use).
= can use indexes while LIKE queries usually require testing every single record in the result set to filter it out (unless you are using full text search) so = has better performance.
LIKE does matching like wildcards char [*, ?] at the shell
LIKE '%suffix' - give me everything that ends with suffix. You couldn't do that with =
Depends on the case actually.
There is another reason for using "like" even if the performance is slower: Character values are implicitly converted to integer when compared, so:
declare #transid varchar(15)
if #transid != 0
will give you a "The conversion of the varchar value '123456789012345' overflowed an int column" error.