While inserting multiple rows what does the statement 'select 1 from dual' do? - sql

While inserting multiple rows into a table using the following style :
insert all
into ghazal_current (GhazalName,Rating) values('Ajab Apna Haal Hota Jo Visaal-e-Yaar Hota',5)
into ghazal_current (GhazalName,Rating) values('Apne Hothon Par Sajana Chahta Hun',4)
into ghazal_current (GhazalName,Rating) values('Shaam Se Aankh Mein Nami Si Hai',4)
into ghazal_current (GhazalName,Rating) values('Tumhe Yaad Ho Ke Na Yaad Ho',3)
select 1 from dual;
What does the statement select 1 from dual mean ? What is it here for ?

DUAL is a built-in table, useful because it is guaranteed to return only one row. This means DUAL may be used to get pseudo-columns such as user or sysdate, the results of calculations and the like. The owner of DUAL is SYS but it can be accessed by every user. DUAL is well-covered in the documentation. Find out more.
In your case, SELECT 1 FROM DUAL; will simply returns 1. You need it because the INSERT ALL syntax demands a SELECT clause but you are not querying the input values from a table.

Brief re-introduction to one-row tables
Some SQL databases require all values to come FROM a table or table-like object, whereas others permit queries to construct values ex nihilo:
-- MySQL, sqlite, PostgreSQL, HSQLdb, and many others permit
-- a "naked" select:
SELECT 1;
-- Others *require* a FROM target, like Oracle.
SELECT 1 FROM DUAL;
-- ...and Firebird/Interbase:
SELECT 1 FROM RDB$DATABASE;
-- ...and DB2:
SELECT 1 FROM SYSIBM.SYSDUMMY1;
Here the cardinality of DUAL is important. If it had more than one row, your result set would have more than one row. What happens, for example, when you SELECT 1 FROM A_Table_With_Ten_Rows?
Why DUAL is used here
The SQL construct VALUES (<row-value-expression>) is a row value constructor. VALUES (1, 2, 3) "creates" a row of values just as SELECT 1, 2, 3 does.
Oracle, of course, requires that these values come FROM somewhere.
As a demonstration, instead of SELECTing from DUAL at the end of the INSERT ALL, try a table with N rows, and you'll see that each VALUES() row is inserted N times.

There are some samples about using dual in Queries:
select sysdate from dual /--it returns date of system
SELECT chr(223) FROM dual /--it returns character of Asciهi code
select my_sequence.nextval from dual; /-- It returns the next value of a sequence
select to_char(sysdate,'yyyy/mm/dd','nls_calendar=persian')from dual
/--returns persian date of system

Related

Error while running very long SQL query with UNION ALL operator in Vertica

This is a sample of subquery used in Vertica Query which is a string generated from the application.
SELECT 1 as ID, 345.45 as PaidAmt FROM DUAL
UNION ALL
SELECT 2 as ID, 789.45 as PaidAmt FROM DUAL
UNION ALL
...
...
There are some cases when this subquery becomes huge as the number of rows with UNION ALL increases. Vertica supports this query to some extent. But when there is let's say 3000 + UNION ALL operator used in a subquery it throws an error.
[SQL Error [4963] [54001]: [Vertica]VJDBC ERROR: The query
contains a SET operation tree that is too complex to analyze
I could not find any documents that talk about the limited use of UNION ALL operator in query or length of the query string.
Is there any system parameter in Vertica or Linux for which we can change the value to successfully execute the query?
I have an alternate approach to fix the query removing UNION ALL. But looking for a solution to the error generated.
Thanks in Advance!
If the CSV option proves impossible, I would use a temporary table - and it would also speed up your query:
CREATE LOCAL TEMPORARY TABLE helper_table(id,paidamt)
ON COMMIT PRESERVE ROWS AS
SELECT 1, 345.45
UNION ALL SELECT 2, 789.45
UNION ALL SELECT 3, 213.44
[.2997 more rows . .]
;
INSERT INTO helper_table
SELECT 3001, 4345.45
UNION ALL SELECT 3002, 3789.45
UNION ALL SELECT 3003, 1213.44
[.2997 more rows . .]
;
SELECT
<<whatever>>
FROM helper_table JOIN <<other_tables>> ON <<whatever>>
;
The helper_table will die as soon as you log off again.
Alternatively, use vsql with a script like this:
CREATE LOCAL TEMPORARY TABLE helper_table (
id INT
, paidamt NUMERIC(9,2)
)
ON COMMIT PRESERVE ROWS;
COPY helper_table FROM stdin;
1| 345.45
2| 789.45
3| 213.44
3001| 4345.45
3002| 3789.45
3003| 1213.44
\.
-- Now you can work with it ...
SELECT * FROM helper_table;

selecting only NON NULL values in Oracle sql table

I have a table that has 40 columns/headers and 15 rows(may vary due to the high volume records); In the records/data, many columns which have NULL values or in other words, these columns were not in a production environment, so no validation required or to list in the output.
I wanna list only the NON NULL values(Column vise) in the select table even if the entire Column is NULL.
COLUMNS
Col_A
Col_B
Col_C
Col_D
Col_E
Col_F
ROW1
Val_1
Val_2
NULL
Val_4
Val_5
Val_6
ROW2
Val_1
Val_2
NULL
Val_4
Val_5
NULL
Here I want to list all the columns except "Column C" which is NULL
In sql this is not possible, because that is not how a sql query works. In short this is what happens
You tell the database engine what columns you want to get back and what the conditions are (conditions filter rows, not columns). At this point the database does not know anything about the results. This is done using the query syntax.
The db engine runs the query and returns the result, row by row. The db engine does not know what is in those rows/columns.
The requirement is to skip columns that have no data. As explained above, that is not know at the time of running the query, but you could work around this, for example by creating a view that only has the columns with data. Bear in mind that this means that every query has to run at least once before the query itself, which could be a downside if you're talking about large datasets.
Lets create a sample table
CREATE TABLE tab1 (c1, c2, c3, c4) AS
(
SELECT 1,CAST(NULL AS NUMBER), 2,4 FROM DUAL UNION ALL
SELECT NULL,NULL, 1,3 FROM DUAL UNION ALL
SELECT 1,NULL, NULL,3 FROM DUAL UNION ALL
SELECT 1,NULL, 2,NULL FROM DUAL UNION ALL
SELECT 4,NULL, 3,4 FROM DUAL
);
Now it's not possible to know which columns have only NULL values before we run the query, but we can run a query to know which columns have only NULL values using an aggregate function like MAX, MIN OR SUM. Lets call this QUERY1. For example:
SELECT MAX(c1),MAX(c2),MAX(c3),MAX(c4) FROM tab1;
MAX(C1) MAX(C2) MAX(C3) MAX(C4)
---------- ---------- ---------- ----------
4 3 4
Now we can convert that select so it generates another select that that only selects the columns with not null values. Lets call this QUERY2.
SELECT
'SELECT '||
RTRIM(
NVL2(SUM(c1),'c1,','') ||
NVL2(SUM(c2),'c2,','') ||
NVL2(SUM(c3),'c3,','') ||
NVL2(SUM(c4),'c4,','')
,',')||' FROM tab1;' FROM tab1;
STMT
---------------------------------------------------------------
CREATE OR REPLACE VIEW tab1_v AS SELECT c1,c3,c4 FROM tab1;
There you go - this statement will only return the columns that have no NULL values. Note that this is not foolproof. If a row is created or updated after you run QUERY1 but before you run QUERY2 that would alter the results of QUERY1, it could not select the correct columns.

Select data from dual table

I have a data as following:
1203
1222
3201
4300
Which are numbers of products, so i need to select them as a data in table ..
I think the solution will be with using dual table ..
I tried the following code:
Select * from { values '1203','1222','3201','4300'} as Table1
But it not working !
Oracle has the TABLE function, which takes as input a varray and returns an anonymous table (anonymous means "the table doesn't have a name"), with a single column named column_value.
Oracle also has the function sys.odcinumberlist(), which takes as input a comma-separated list of numbers and returns a varray of numbers. (Similarly, to generate a varray of varchar2 values, there is sys.odcivarchar2list().)
To input your for values and return a result with a single column named num (or any other name you want), you can use these two functions together - and alias the column in the select clause. Like this:
select column_value as num
from table( sys.odcinumberlist( 1203, 1222, 3201, 4300 ) )
;
NUM
----
1203
1222
3201
4300
In standard SQL you would need to use:
Select *
from (values ('1203','1222','3201','4300')) as Table1;
That would create a single row with four (character) columns. If you intended to return four rows it would be:
Select *
from (values ('1203'),('1222'),('3201'),('4300')) as Table1
However, Oracle does NOT support that syntax. Neither does it support a SELECT without a FROM clause.
If you want a single row with 4 columns in Oracle you need
select '1203','1222','3201','4300'
from dual;
If you want four rows you need
select '1203'
from dual
union all
select '1222'
from dual
union all
select '3201'
from dual
union all
select '4300'
from dual;
Additionally: '1203' is not a "number". It's a character string. Number literals are written without quotes in SQL: 1203 is a number
You can also use XMLTABLE.
select TO_NUMBER(TRIM(COLUMN_VALUE)) as numbers from XMLTABLE( '1203,1222,3201,4300');
Numbers
-------
1203
1222
3201
4300
This works only for numbers.
EDIT: Better to wrap it with to_number as suggested by experts in the comments.

How to insert multipleRows in oracle using sequence

I need to insert multiple Rows in oracle database, I use this command line:
INSERT ALL
INTO PHMR_VIP (PHMR_VIP_ID,PHMR_VIP_NOM,PHMR_VIP_PRENOM) VALUES (SQ_PHMR_VIP.nextval, 'dfdf', 'dfdfd')
INTO PHMR_VIP (PHMR_VIP_ID,PHMR_VIP_NOM,PHMR_VIP_PRENOM) VALUES (SQ_PHMR_VIP.nextval, 'ffdf', 'dfdf')
INTO PHMR_VIP (PHMR_VIP_ID,PHMR_VIP_NOM,PHMR_VIP_PRENOM) VALUES (SQ_PHMR_VIP.nextval, 'mohfdfd','fdfdf')
SELECT * FROM dual;
But, I have oracle error:
ORA-00001: violation de contrainte unique (PHMR.PHMR_VIP_PK)
How can I resolve this please? I need to do a bulkInsert with column PHMR_VIP_ID as a sequence
You can use:
INSERT INTO PHMR_VIP (PHMR_VIP_ID,PHMR_VIP_NOM,PHMR_VIP_PRENOM)
SELECT SQ_PHMR_VIP.nextval, col1, col2
FROM (
SELECT 'dfdf' AS col1, 'dfdfd' AS col2 FROM dual
UNION ALL
SELECT 'ffdf', 'dfdf' FROM dual
UNION ALL
SELECT 'mohfdfd','fdfdf' FROM dual
);
For some, you have to use SELECT 1 FROM dual; instead of SELECT * FROM dual;. See this reference: https://community.oracle.com/thread/2457262. This is because there is only 1 row in dual.
That doesn't help in this instance though, because you can't use sequences with SELECT ALL, per this article: https://community.oracle.com/thread/1038439, at least not the way you have. You can if you have a trigger that catches each nextval call and updates the value manually, but as mentioned further in the postings, it can decrease performance.
The recommendation is to use multiple inserts rather than an insert all.
Hope this helps.
-C§

Oracle Select numbers from an IN clause

I'm looking for the best way to select numbers directly from an in clause.
Basically like:
SELECT * FROM (2,6,1,8);
That doesn't work. I can do it this way:
SELECT Lv FROM ( SELECT Level LV
FROM DUAL
CONNECT BY Level < 20)
WHERE Lv IN (2,6,1,8);
But that seems to be a bit clunky. Is there a more elegant way?
You can do
select column_value from table(sys.dbms_debug_vc2coll(1,2,3,4,5));
but that actually returns a varchar2. You can create your own TYPE and use that
create type tab_num is table of number;
/
select column_value from table(tab_num(1,2,3,4,5));
It's also worth looking at the MODEL clause. It looks complicated, but it is very good at generating data
SELECT x from dual
MODEL DIMENSION BY (1 AS z) MEASURES (1 x)
RULES ITERATE (7) (x[ITERATION_NUMBER]=ITERATION_NUMBER+1)
It's more elegant if you materialize an auxiliary numbers table:
SELECT num FROM numbers WHERE num IN (2,6,1,8);
And this is also useful when combined with another table.
For instance, I've had a case where I needed to populate large configuration tables with changes from piecewise results:
Big SP or Excel sheet or report identifies missing cost centers in config gives a large set of results which need to be inserted with varying data in some groups.
Paste partial results into a individual comma separated lists:
INSERT INTO {stuff}
SELECT {stuff}, 130 as line_item
FROM numbers
WHERE numbers.num IN ({pasted a section of results})
INSERT INTO {stuff}
SELECT {stuff}, 135 as line_item
FROM numbers
WHERE numbers.num IN ({pasted another section of results})
If you don't explicitly need the IN clause, you could use UNION:
select 2 from dual
union
select 6 from dual
union
select 1 from dual
union
select 8 from dual
There is a more elegant variant to INSERT multiple rows into a table:
INSERT ALL
INTO table (col) VALUES ('a')
INTO table (col) VALUES ('b')
INTO table (col) VALUES ('c')
SELECT * FROM dual;
But I don't know a way to do that for a SELECT.