ORA-00904 with UNION and ORDER BY alias [duplicate] - sql

The following query is perfectly valid in pretty much every database (give or take a dual dummy table), including Oracle:
select 'A' as x from dual union all
select 'B' from dual
order by x asc
Returning:
| X |
|---|
| A |
| B |
Now this query is still quite standard SQL, but doesn't work on Oracle
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
order by x asc
I'm getting
ORA-00904: "X": invalid identifier
This, however, works:
select 'A' as x from dual union all
select 'B' as x from dual union all
select 'C' from dual
order by x asc
I've been playing around with this issue and figured out that apparently, at least the first subselect and the second-last (??) subselect need to have a column called x. In the first example, the two subselects seemed to simply coincide. Working example:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' from dual union all
select 'F' as x from dual union all
select 'G' from dual
order by x asc
As you may have guessed, this wouldn't work:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' as x from dual union all
select 'F' from dual union all
select 'G' from dual
order by x asc
Interesting side-note:
Derived tables seem not to suffer from this limitation. This works:
select * from (
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
)
order by x asc
Question:
Is this a (known?) bug in the Oracle SQL parser, or is there any very subtle detail in the language syntax that absolutely requires the first and the second-last subselect to hold a column of the name as referenced from the ORDER BY clause?

This doesn't really answer the question, but it seems to be a parser bug (or 'feature') rather than a language requirement.
According to My Oracle Support, this seems to have been raised as bug 14196463 but closed with no resolution. It's also mentioned in community thread 3561546. You need a MOS account, or at least an Oracle account, to see either of those though.
It's also been discussed in an OTN thread which requires a basic Oracle login rather than a MOS account, as far as I can tell. That also doesn't have much information but repeats your findings, and also suggests the behaviour has existed back at least to 9.2.0.8 and perhaps much earlier.
The documentation is a bit vague but doesn't indicate this is expected to be a problem:
For compound queries containing set operators UNION, INTERSECT, MINUS, or UNION ALL, the ORDER BY clause must specify positions or aliases rather than explicit expressions. Also, the ORDER BY clause can appear only in the last component query. The ORDER BY clause orders all rows returned by the entire compound query.
You are aliasing your expression and using that, and it doesn't say you have to alias particular components (although of course it doesn't say you don't have to either).
The behaviour seems inconsistent with the alias being valid for the final projection, and the usual rule about the alias only being valid in the order by clause - this seems to be falling down somewhere in between.

This doesn't answer why you are getting inconsistent behavior from your current query, but in Oracle you can easily rewrite as the following (which should never fail with an invalid identifier error):
with t(x) as (
select 'A' from dual
union all
select 'B' from dual
union all
select 'C' from dual
)
select * from t
order by x asc
With the added bonus that you only specify the column alias (x) once.

Related

oracle query to show tourist_name' and the places which is not visited by tourist

I have one table with two columns in it. First one is 'tourist_name' and second one is 'visited_places'. So I need a query which will give me following output :
'tourist_name' and the places which is not visited by tourist.
You can generate the rows using cross-join and then simply use minus clause to get your desired result -
WITH TAB AS (SELECT 1 TOURIST_NAME, 'B' VISITED_PLACE FROM DUAL UNION ALL
SELECT 1, 'C' FROM DUAL UNION ALL
SELECT 1, 'D' FROM DUAL UNION ALL
SELECT 2, 'A' FROM DUAL UNION ALL
SELECT 2, 'E' FROM DUAL)
SELECT TOURIST_NAME, VISITED_PLACE FROM (SELECT DISTINCT VISITED_PLACE FROM TAB),
(SELECT DISTINCT TOURIST_NAME FROM TAB)
MINUS
SELECT TOURIST_NAME, VISITED_PLACE FROM TAB;
Link.

Sql Only String search

with temp(name) as (select 'abc' from dual
union select '123abc' from dual
union select '1abc3' from dual)
select * from temp where temp.name like '%[a-z]%'
why i am not able to get all the 3 records in output
, I am using Oracle SQL Developer 11g
Reason why i am using this query is : I want to check if Desired column Contains only String no Number and Special Character
You are mixing SQL Server and Oracle syntax:
SQL SERVER Demo:
with temp(name) as (
select 'abc' union all select '123abc' union select '1abc3'
)
select * from temp where temp.name like '%[a-z]%';
-- [] is T-SQL specific
ORACLE Demo:
with temp(name) as (select 'abc' from dual
union select '123abc' from dual
union select '1abc3' from dual)
select * from temp where regexp_like(temp.name, '[a-z]')
First of all, you are mixing concepts. You are trying to do a regular expression compare by using a normal LIKE operator. Secondly, you should tag your question with the database you are using. I am assuming that you are using oracle, given the dual table.
WITH temp(name) AS (SELECT 'abc' FROM dual
UNION SELECT '123abc' FROM dual
UNION SELECT '1abc3' FROM dual)
SELECT * FROM temp
WHERE REGEXP_LIKE(temp.name,'[a-z]+')
Also note that using the % wildcard character will not work as you expect it to in a regular expression match.
Fist, it is better to use union all rather than union, because union incurs overhead for removing duplicates.
Second, your like pattern is non-standard, supported only in SQL Server and Sybase. In other words, none of your names contain square braces or hyphens, so none match the pattern.
Does this do what you expect?
with temp(name) as (
select 'abc' from dual union all
select '123abc' from dual union all
select '1abc3' from dual
)
select *
from temp
where temp.name like '%a%';
This is only checking for syntax. It is not equivalent to your like pattern.
I speculate from the syntax that you are using Oracle. If so, then you can use regular expressions:
where regexp_like(temp.name, '[a-z]')
Most (but not all) databases support regular expressions, so you can express similar logic in most databases.

ORDER BY in UNION does not work [duplicate]

The following query is perfectly valid in pretty much every database (give or take a dual dummy table), including Oracle:
select 'A' as x from dual union all
select 'B' from dual
order by x asc
Returning:
| X |
|---|
| A |
| B |
Now this query is still quite standard SQL, but doesn't work on Oracle
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
order by x asc
I'm getting
ORA-00904: "X": invalid identifier
This, however, works:
select 'A' as x from dual union all
select 'B' as x from dual union all
select 'C' from dual
order by x asc
I've been playing around with this issue and figured out that apparently, at least the first subselect and the second-last (??) subselect need to have a column called x. In the first example, the two subselects seemed to simply coincide. Working example:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' from dual union all
select 'F' as x from dual union all
select 'G' from dual
order by x asc
As you may have guessed, this wouldn't work:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' as x from dual union all
select 'F' from dual union all
select 'G' from dual
order by x asc
Interesting side-note:
Derived tables seem not to suffer from this limitation. This works:
select * from (
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
)
order by x asc
Question:
Is this a (known?) bug in the Oracle SQL parser, or is there any very subtle detail in the language syntax that absolutely requires the first and the second-last subselect to hold a column of the name as referenced from the ORDER BY clause?
This doesn't really answer the question, but it seems to be a parser bug (or 'feature') rather than a language requirement.
According to My Oracle Support, this seems to have been raised as bug 14196463 but closed with no resolution. It's also mentioned in community thread 3561546. You need a MOS account, or at least an Oracle account, to see either of those though.
It's also been discussed in an OTN thread which requires a basic Oracle login rather than a MOS account, as far as I can tell. That also doesn't have much information but repeats your findings, and also suggests the behaviour has existed back at least to 9.2.0.8 and perhaps much earlier.
The documentation is a bit vague but doesn't indicate this is expected to be a problem:
For compound queries containing set operators UNION, INTERSECT, MINUS, or UNION ALL, the ORDER BY clause must specify positions or aliases rather than explicit expressions. Also, the ORDER BY clause can appear only in the last component query. The ORDER BY clause orders all rows returned by the entire compound query.
You are aliasing your expression and using that, and it doesn't say you have to alias particular components (although of course it doesn't say you don't have to either).
The behaviour seems inconsistent with the alias being valid for the final projection, and the usual rule about the alias only being valid in the order by clause - this seems to be falling down somewhere in between.
This doesn't answer why you are getting inconsistent behavior from your current query, but in Oracle you can easily rewrite as the following (which should never fail with an invalid identifier error):
with t(x) as (
select 'A' from dual
union all
select 'B' from dual
union all
select 'C' from dual
)
select * from t
order by x asc
With the added bonus that you only specify the column alias (x) once.

Curious issue with Oracle UNION and ORDER BY

The following query is perfectly valid in pretty much every database (give or take a dual dummy table), including Oracle:
select 'A' as x from dual union all
select 'B' from dual
order by x asc
Returning:
| X |
|---|
| A |
| B |
Now this query is still quite standard SQL, but doesn't work on Oracle
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
order by x asc
I'm getting
ORA-00904: "X": invalid identifier
This, however, works:
select 'A' as x from dual union all
select 'B' as x from dual union all
select 'C' from dual
order by x asc
I've been playing around with this issue and figured out that apparently, at least the first subselect and the second-last (??) subselect need to have a column called x. In the first example, the two subselects seemed to simply coincide. Working example:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' from dual union all
select 'F' as x from dual union all
select 'G' from dual
order by x asc
As you may have guessed, this wouldn't work:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' as x from dual union all
select 'F' from dual union all
select 'G' from dual
order by x asc
Interesting side-note:
Derived tables seem not to suffer from this limitation. This works:
select * from (
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
)
order by x asc
Question:
Is this a (known?) bug in the Oracle SQL parser, or is there any very subtle detail in the language syntax that absolutely requires the first and the second-last subselect to hold a column of the name as referenced from the ORDER BY clause?
This doesn't really answer the question, but it seems to be a parser bug (or 'feature') rather than a language requirement.
According to My Oracle Support, this seems to have been raised as bug 14196463 but closed with no resolution. It's also mentioned in community thread 3561546. You need a MOS account, or at least an Oracle account, to see either of those though.
It's also been discussed in an OTN thread which requires a basic Oracle login rather than a MOS account, as far as I can tell. That also doesn't have much information but repeats your findings, and also suggests the behaviour has existed back at least to 9.2.0.8 and perhaps much earlier.
The documentation is a bit vague but doesn't indicate this is expected to be a problem:
For compound queries containing set operators UNION, INTERSECT, MINUS, or UNION ALL, the ORDER BY clause must specify positions or aliases rather than explicit expressions. Also, the ORDER BY clause can appear only in the last component query. The ORDER BY clause orders all rows returned by the entire compound query.
You are aliasing your expression and using that, and it doesn't say you have to alias particular components (although of course it doesn't say you don't have to either).
The behaviour seems inconsistent with the alias being valid for the final projection, and the usual rule about the alias only being valid in the order by clause - this seems to be falling down somewhere in between.
This doesn't answer why you are getting inconsistent behavior from your current query, but in Oracle you can easily rewrite as the following (which should never fail with an invalid identifier error):
with t(x) as (
select 'A' from dual
union all
select 'B' from dual
union all
select 'C' from dual
)
select * from t
order by x asc
With the added bonus that you only specify the column alias (x) once.

interesting behaviour of order by with union all clause

I encountered just an interesting behaviour of order by clause when query contains union all.
For example I have following query:
select * from dual order by 1
union all
select * from dual
It fails, what the?
Ok it seems that oracle just does not like order by followed by union all. Lets rewrite query to following:
select * from (select * from dual order by 1)
union all
select * from dual
It is fixed!
It will also work if I just swap two queries, so one with order by goes to the end:
select * from dual
union all
select * from dual order by 1
That seems to be inconsistent. So what is the cause of such behaviour? Is it some kind of bug or it is done on purpose?
The statement
select * from (select * from dual order by 1)
has no defined order at all. Only the outermost ORDER BY takes effect in SQL (except if there is a row limit set).
If you still happen to observe order in the query results this is a coincidence that can go away at any time.
In the statement
select * from dual
union all
select * from dual order by 1
The order by is attached to the union all, not the the 2nd select. It is therefore top-level and well-defined.
Use the last form. And put the order by into a new line to make this easier to read.
How can I then sort just single select with union all?
The output order of union all is undefined without order-by clause. Certainly the two inputs are not guaranteed to be concatenated.
select *, 1 as Tag from dual
union all
select *, 2 as Tag from dual
order by Tag, 1 --simulate ordered concatenation of inputs