How does Oracle SELECT FROM dual work with multiple fields - sql

Here's the structure of a query I came across:
MERGE INTO TABLE t
USING (SELECT ? id, ? email, ? cr_date, ? info, ? status FROM dual) n
ON t.id=n.id and t.email=n.email
WHEN MATCHED THEN UPDATE SET z.info = n.info z.status='Y'
WHEN NOT MATCHED THEN INSERT (info, status) VALUES (n.info, n.status)
I've read up on using DUAL to return SYSDATE or other operations... is the SELECT simply returning some input values into a table (row) to simplify further operations in the other clauses?
Thanks!

The code you came across is meant to update a single row, or create it if it doesn't exist.
DUAL is a special system table containing just one row.
Selecting from DUAL is a workaround for Oracles inability to do simply:
select sysdate;
Note that it doesn't have to be dual, it can be any one-row-table or even a query that returns one row.
select sysdate
from dual;
is equivalent to:
select sysdate
from my_one_row_table;
and
select sysdate
from my_table
where my_primary_key = 1;
Since version 10g, the dual table has a special access path which shows up in the execution plan as "fast dual", which results in 0 consistent gets, which isn't possible to achive on your own using other tables.

a) Yes you can use like this statement. But you must rename your "date" field name cause its keyword of oracle.
b) but i stongly recommend to create procedure for this.

Read about DUAL table : http://www.orafaq.com/wiki/Dual
It commonly used for SYSDATE, Can be used for multiple fields such as below too:
SELECT USER, sysdate from dual;

The statement appears to be doing essentially an Update Else Insert using a little trick with DUAL. The "?" appear to be bind variables.
The same logic could look like (in pseudocode):
UPDATE t
SET t.id= ?,
t.email= ?,
t.status= 'Y'
IF update updated 0 rows THEN
INSERT into t
VALUES (?, ?)
where the two ? are the "info" and "status" variables respectively.
Using DUAL just reduces your work into one database call instead of two.

Related

Is there a system table that updates and returns its row based on a query?

DUAL is a system table that is used to get constants and results of system functions.
However it only has one column named "dummy" and only a row with X value in it so this doesnt work:
My question is, is there a system table that can pull this trick off? A (single-column) table that returns a row regardless of how its one column is queried, with the value in the where clause.
What you want to do violates how SQL works. However, if you always wnat to return exactly one row from a "table", you can use aggregation with no group by:
select max(dummy)
from dual
where dummy = '5'
The returns value is NULL.
Perhaps it would be easier to suggest something if you explained what problem you are trying to solve.
As you asked:
A (single-column) table that returns a row regardless of how its one column is queried, with the value in the where clause.
SQL> select dummy from dual where dummy = '5' or 1 = 1;
D
-
X
SQL>
dual is a (single-column) table
this query returned a row
value ('5') is in its where clause
I presume that "regardless of how its one column is queried" is also satisfied
Why "where clause"?
SELECT '5' AS dummy FROM dual
DUMMY|
-----|
5 |

Select from nothing in Oracle without referencing the dual table?

selecting from nothing in Oracle SQL happens while referencing the dual table, like
SELECT sysdate FROM dual;
Now I'd like to have a query that also works for PostgreSQL, but selecting from dual there isn't possible. I know that I can drop the whole FROM part, but then it won't work in Oracle.
I've also tried things like SELECT CURRENT_TIMESTAMP FROM VALUES(1)) V(C);, but Oracle can't do this, either.
So is there a way to select from nowhere without using the dual table in Oracle SQL?
Alternatively, create a table named dual in Postgres, made of 1 row and 1 column
create table dual as (select 1);
and you can use it in Postgres as you would in Oracle
select 'whatever' from dual;
?column?
-----------
whatever
sysdate in Oracle is a built-in function, i.e. not a database table column. You can use any table as long as the query returns precisely one row, e.g.
select sysdate from EMP where rownum < 2
If you have a small table, TABLE_B, with at least one row, you could try selecting a single row from it.
select sysdate from TABLE_B where rownum < 2;
The contents of the table don't matter because you won't be selecting any of its columns.
The below code generates a fake row in both Oracle and Postgres (10+), using the XMLTABLE function. This code is pretty weird but it doesn't require any custom objects.
--Generate a fake row in either Oracle or Postgres.
select *
from xmltable
(
--The expression syntax is different for Oracle and Postgres.
--Oracle can use a literal, Postgres must reference the XML.
--The string '' is null in Oracle but not null in Postgres.
case when '' is null then '1' else '/a' end passing '<a>1</a>'
columns test int path '.'
);
test
----
1

Firebird SQL: pass multi-row data in the query text

is it possible to use an array of elements as a select statement?
I know it is possiible to get rows based on static elements like this:
SELECT 405, CAST('4D6178' AS VARCHAR(32)), CAST('2017-01-01 00:00:00' AS TIMESTAMP) FROM rdb$databas
That will give you a table select with one row.
Now I would like to get this as table with n rows, but I don't know how to achieve this. Due to the fact that firebird doesn't allow multiple select statements I cannot only append n times a selec.
Info : Firebird 2.1
Use UNION ALL clause.
https://en.wikipedia.org/wiki/Set_operations_(SQL)#UNION_operator
Select x,y,z From RDB$DATABASE
UNION ALL
Select a,b,c From RDB$DATABASE
UNION ALL
Select k,l,m From RDB$DATABASE
Notice however that this should only be used for small data. Firebird query length is limited to 64KB and even if that would not be so - abusing this method to inject lots of data would not be good.
If you really need to enter lot of similar (same structure) data rows - use Global Temporary Tables
The following discussion hopefully would give you more insights:
https://stackoverflow.com/a/43997801/976391

Fetch multi output from SQL Transformation at Informatica

I want to fetch query result from informatica SQL Transformation.
I get a sql query to an input port(QUERY) also want to fetch sysdate
SELECT (~QUERY~),SYSDATE FROM DUAL;
But it does not let me to fetch such a result as 2 output column.
When I write
~QUERY~
it is giving me result, but I need 2nd or 3rd column.
Thanks
Ok, first try putting sysdate into the query as one of the columns rather than encapsulating and selecting from dual
e.g. SELECT A.COLUMN, A.COLUMN2, SYSDATE, A.COLUMN3 FROM TABLENAME A WHERE CONDITION
Then if you want a multi row return you can use an inline lookup configured to return multiple rows (cant select from dual in a lookup). The one gotcha is that you must be on powercenter 9.1 or higher... otherwise you'll need to put that query in a source qualifier and use a joiner to bring it into the main pipeline. Why sysdate from the database rather than the native informatica SYSTIMESTAMP function?
My code was working with 9.5.1, have problem with 9.6.1
SELECT (~QUERY~),SYSDATE FROM DUAL;
You can put as statement to assign column to output port. Assume that outport port is RESULT and DATETIME
SELECT (~QUERY~) RESULT ,SYSDATE DATETIME FROM DUAL;

How to make result set from ('1','2','3')?

I have a question, how can i make a result set making only list of values. For example i have such values : ('1','2','3')
And i want to make a sql that returns such table:
1
2
3
Thanks.
[Edit]
Sorry for wrong question.
Actually list not containing integers, but it contains strings.
I am currently need like ('aa','bb,'cc').
[/Edit]
If you want to write a SQL statement which will take a comma separate list and generate an arbitrary number of actually rows the only real way would be to use a table function, which calls a PL/SQL function which splits the input string and returns the elements as separate rows.
Check out this link for an intro to table-functions.
Alternatively, if you can construct the SQL statement programmatically in your client you can do:
SELECT 'aa' FROM DUAL
UNION
SELECT 'bb' FROM DUAL
UNION
SELECT 'cc' FROM DUAL
The best way I've found is using XML.
SELECT items.extract('/l/text()').getStringVal() item
FROM TABLE(xmlSequence(
EXTRACT(XMLType(''||
REPLACE('aa,bb,cc',',','')||'')
,'/all/l'))) items;
Wish I could take credit but alas : http://pbarut.blogspot.com/2006/10/binding-list-variable.html.
Basically what it does is convert the list to an xmldocument then parse it back out.
The easiest way is to abuse a table that is guaranteed to have enough rows.
-- for Oracle
select rownum from tab where rownum < 4;
If that is not possible, check out Oracle Row Generator Techniques.
I like this one (requires 10g):
select integer_value
from dual
where 1=2
model
dimension by ( 0 as key )
measures ( 0 as integer_value )
rules upsert ( integer_value[ for key from 1 to 10 increment 1 ] = cv(key) )
;
One trick I've used in various database systems (not just SQL databases) is actually to have a table which just contains the first 100 or 1000 integers. Such a table is very easy to create programatically, and your query then becomes:
SELECT value FROM numbers WHERE value < 4 ORDER BY value
You can use the table for lots of similar purposes.