How does Reserved keyword * works in sql - sql

How does rdbms tools execute * in select statements. reason of asking the question is its different usage in different rdbms tools.
Ex: oracle and db2 gives error in below statements, however works fine in mysql,mssql,sybase. Looks like an issue with sql parser.
select col_name,* from table_name
Or
select *,col_name from table_name

Oracle (and probably DB2 as well) accepts an unadorned * only when there are no other column references or expressions in the SELECT.
However, it is always allowed with a table alias. So you can write:
select col_name, t.*
from table_name t
Just one caution: the result set will have two columns with the same name, which can cause other problems.

Db2 11.1 supports unqualified *s. E.g.
db2 "create table table_name( col_name int )"
DB20000I The SQL command completed successfully.
db2 "select col_name,* from table_name"
COL_NAME COL_NAME
----------- -----------
0 record(s) selected.

https://en.wikipedia.org/wiki/SQL#Interoperability_and_standardization
SQL implementations are incompatible between vendors and do not necessarily completely follow standards.
See the Wikipedia link above for some of the "several reasons for this lack of portability between database systems"

Related

Does Actian PSQL 13.31 (Zen) have the equivalent of SQL Server "IN" in WHERE clause?

I have read a ton of Actian PSQL docs but cannot find out how to duplicate this simple SQL verb:
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1, value2, ...);
Does Actian PSQL 13.31 have the equivalent of SQL Server IN in the WHERE clause?
They do have an IN verb but it does something totally different.
This seems to work fine. The formatting of the statement has no impact.
select * from "Class" WHERE ID IN (160, 161 )
If you run that SQL in PCC in the DemoData db I get only two records. Not sure what I was doing wrong but you guys got me going. Thank you.

Why does a "WITH" clause give a syntax error on Informix?

I am trying a query similar to the below one on Informix, but I get a syntax error (-201: "A syntax error has occurred") every time.
with a_qry (locationnames) as (SELECT * FROM TABLE(LIST{'abc','xyz'}))
select locationnames from a_qry;
Can someone please help with this?
Informix 14.10 and later
Informix 14.10 (released in March 2019) added support for the WITH statement (Common Table Expressions).
Informix 12.10 and earlier
The documentation for the Informix SELECT statement in Informix 12.10 (which was the latest when this question was asked) does not include the WITH clause because the server does not support the WITH clause and common table expressions (CTEs) — a grievous omission, but nevertheless a fact of life.
For your specific example, you could use:
SELECT locationnames
FROM (SELECT * FROM TABLE(LIST{'abc','xyz'})(locationnames));
which would yield:
abc
xyz
though the sub-query isn't necessary here, of course (you could simply use SELECT * FROM TABLE(LIST{'abc','xyz'})(locationnames) to get the same result). In general, though, you'll have to write out each reference to a CTE in full, with the consequential risk that the optimizer doesn't spot the commonality and therefore doesn't optimize as well as it might if it could.
You can try to use a temp table (which doesn't require special permission).
select * from (your query)
into temp myTmpTable;
select * from MyTmpTable;

SQL - conditionally select a column if exists

I need to select a column only if it exists in table, else it can be set to null.
Sample table below, lets say the marks col is not necessary be there, so need to be checked if it exists
Table1:
name marks
joe 10
john 11
mary 13
Query:
select
name,
marks if it exists else null as marks1 -- pseudo code
from
table1
What should go in line to select marks ?
SQL Doesn't permit that. Your result set has two options:
Static inclusion
All from table or subquery through column-expansion with * and tbl.*
Perhaps this will suit your needs, SELECT * FROM table1; You'll always get that column, if it exists.
try this
IF COL_LENGTH('your_table_name','column_name_you_want_to_select') IS NULL BEGIN
--This means columns does not exist or permission is denied
END
else
--Do whatever you want
It is possible to achieve this in PostgreSQL using JSON. Consider the following SQL query:
SELECT c.relname, c.relkind, c.relispartition
FROM pg_class c
WHERE c.relkind IN ('r','p') AND
c.relnamespace=(SELECT oid FROM pg_namespace WHERE nspname='public')
In PostgreSQL 10+, that will show you the names of all the tables in public schema, including whether they are partitioned and if so whether the table is the partitioned table or one of the partitions of it. However, if you try to run the same query on PostgreSQL 9.6 or earlier, it will fail since the relispartition column does not exist on the pg_class table prior to PostgreSQL 10.
An obvious solution would be to dynamically generate the SQL based on a condition, or have two different versions of the SQL. However, suppose you don't want to do that, you want to have a single query which works on both versions – in other words, you want to conditionally select the relispartition column if it exists.
The core SQL language does not have any facility to conditionally select a column, but it is achievable in PostgreSQL using the row_to_json function, as follows:
SELECT c.relname, c.relkind,
(row_to_json(c)->>'relispartition')::boolean AS relispartition
FROM pg_class c
WHERE c.relkind IN ('r','p') AND
c.relnamespace=(SELECT oid FROM pg_namespace WHERE nspname='public')
If you try running that, you will find on PostgreSQL 10+ the relispartition column is returned as true/false, whereas in pre-10 versions it is NULL. You could make it return false instead of NULL in pre-10 versions by doing COALESCE((row_to_json(c)->>'relispartition')::boolean,false).
What this is doing, is row_to_json(c) turns all the data of the row into JSON. Next, ->>'relispartition' selects the value of the relispartition JSON object key as text, which will be the same as the value of the relispartition column; if there is no such key in the JSON, the result of that will be NULL. Then, ::boolean converts the string value true/false back into a PostgreSQL boolean value. (If your column is of some other type, use the appropriate cast for the type of your column.)
(Obviously this approach will not work in Postgres versions which are too old to have the necessary JSON support – I have tested it works in Postgres 9.4; while I haven't tested it in Postgres 9.3, it probably works there. However, I would not expect it to work in 9.2 or earlier – the ->> operator was added in 9.3, and the JSON type and row_to_json function was added in 9.2. However, I expect few people will need to support those old unsupported versions–9.3 was released in 2013, and 9.2 supported ended in 2017.)
Try this:
IF EXISTS( SELECT 1
FROM information_schema.columns
WHERE table_name='your_table' and column_name='your_column') THEN
SELECT your_column as 'some_column'
ELSE
SELECT NULL as 'some_column'
END IF
Replying to an old question yet again but here's my hacky solution to this problem since I don't know how to write SQL functions... yet! %I formats the string as an identifier, and if there is no such table the return value is NULL and the alias is used!
SELECT (SELECT format('%I', 'my_column')
AS my_column_alias
FROM information_schema.columns
WHERE table_name='my_table'
AND column_name='my_column')
FROM source_table
Hope this helps everybody out there =)

Oracle and Sybase compatibility for create table new_table as

I am trying to write an SQL query which needs to be compatible on both a Sybase and Oracle database. The query looks like the following :
SELECT *
INTO new_table
FROM other_table
This query is working great on a Sybase database but not on an Oracle one. I found the equivalent for Oracle :
CREATE table new_table AS
SELECT *
FROM other_table
Is there a way to write a third query that would do the same and that can be executed on a Sybase and on an Oracle database?
As you found, Oracle supports INTO but doesn't use it like Sybase/SQL Server do. Likewise, Sybase doesn't support Oracle's extension of the CREATE TABLE syntax.
The most reliable means of creating a table & importing data between the systems is to use two statements:
CREATE TABLE new_table (
...columns...
)
INSERT INTO new_table
SELECT *
FROM OLD_TABLE
Even then, syntax is different because Oracle requires each statement to be delimited by a semi-colon when TSQL doesn't.
Creating a table & importing all the data from another table is a red flag to me - This is not something you'd do in a stored procedure for a production system. TSQL and PLSQL are very different, so I'd expect separate scripts for DML changes.
There is no query that would do what you want. These environments are very different.
It is possible.
SELECT * INTO new_table FROM existing_table;
Thanks

SQL/JDBC : select query on variable tablenames

I'm using Oracle DB and I would like to write a SQL query that I could then call with JDBC. I'm not very familiar with SQL so if someone can help me, that could be great ! Here is the problem. I have a table MY_TABLE wich contains a list of another tables, and I would like to keep only the nonempty tables and those that their names start by a particular string.
The query I wrote is the following :
select TABLE_NAME
from MY_TABLE
where TABLE_NAME like '%myString%'
and (select count(*) from TABLE_NAME where rownum=1)<>0
order by TABLE_NAME;`
The problem comes from the second SELECT, but I don't know how can I do to use the TABLE_NAME value.
Does someone have an idea ?
Thanks.
[Added from comments]
Actually, I need to test the V$ views contained in the ALL_CATALOG table. But if I can find another table where all these views are contained too and with a NUM_ROWS column too, it would be perfect !
Standard versions of SQL do not allow you to replace 'structural elements' of the query, such as table name or column name, with variable values or place-holders.
There are a few ways to approach this.
Generate a separate SQL statement for each table name listed in MY_TABLE, and execute each in turn. Brute force, but effective.
Interrogate the system catalog directly.
Investigate whether there are JDBC metadata operations that allow you to find out about the number of rows in a table without being tied to the system catalog of the specific DBMS you are using.
Can you use oracle view USER_TABLES? then query will be much easier
select TABLE_NAME
from USER_TABLES
where TABLE_NAME like '%myString%'
and Num_ROWS > 0
order by TABLE_NAME;`