Oracle SQL: Use sequence in insert with Select Statement
Assuming that you want to group the data before you generate the key with the sequence, it sounds like you want something like
INSERT INTO HISTORICAL_CAR_STATS (
HISTORICAL_CAR_STATS_ID,
YEAR,
MONTH,
MAKE,
MODEL,
REGION,
AVG_MSRP,
CNT)
SELECT MY_SEQ.nextval,
year,
month,
make,
model,
region,
avg_msrp,
cnt
FROM (SELECT '2010' year,
'12' month,
'ALL' make,
'ALL' model,
REGION,
sum(AVG_MSRP*COUNT)/sum(COUNT) avg_msrp,
sum(cnt) cnt
FROM HISTORICAL_CAR_STATS
WHERE YEAR = '2010'
AND MONTH = '12'
AND MAKE != 'ALL'
GROUP BY REGION)
Use sequence number with insert select
Keyword distinct
is incompatible with sequence querying. If you really need it, try something like
INSERT INTO mySchema.ODI_PRICELIST_THREAD_TABLE (
src_table,
thread_id,
creation_date)
select
a.src_table,
num_thread_seq.nextval,
a.create_date
from
(select distinct src_table, create_date from mySchema.nb_pricelist_ctrl) a
Insert a sequence and SELECT
INSERT INTO ORDERS(order_id, foo1, foo2, foo3)
SELECT SEQUENCE_ORDERS.nextval,foo1, foo2, foo3
FROM bar
WHERE X = Y
Insert from select with sequence and group by
The problem here is because your sequence is not aggregated, therefore you have this error. Try this way:
insert into tableA (
taba_id,
taba_date,
taba_sum
)
select tabb_sequence.nextval,
tabb_date,
stv
from (select tabb_date,
sum(tabb_value) stv,
from tableB
group by tabb_date) a;
Using Sequence for inserting
To use a sequence to generate IDs, you create it normally in the schema where the table is.
As user application user GEM_APP
:
CREATE TABLE my_table (id NUMBER, col1 ...);
CREATE SEQUENCE my_seq;
The application user itself (and f.i. it's stored procedures) can use the sequence directly:
INSERT INTO my_table (id, col1) VALUES (my_seq.nextval, 'bla');
However, other users need the correct privileges. Usually, you grant select rights on the sequence to the same users or roles you grant insert rights on the table:
GRANT SELECT, INSERT ON my_table TO user_xy;
GRANT SELECT ON my_seq TO user_xy;
Then the other user can insert data into the table, but must qualify the schema:
INSERT INTO gem_app.my_table(id, col1) VALUES (gem_app.my_seq.nextval, 'bla');
You can create aliases to hide the schemas, some people like them, some not, but I would definitely not recommend to use PUBLIC synonyms as they are hard to control and create all kind of namespace clashes.
Oracle SQL: Insert selected values as well as next value from sequence
Your third approach is correct, and works (with consistent column names):
create table my_mapping_table (letter varchar2(1), color varchar2(10));
insert into my_mapping_table (letter, color) values ('N', 'Yellow');
insert into my_mapping_table (letter, color) values ('P', 'Orange');
insert into my_mapping_table (letter, color) values ('Q', 'Violet');
insert into my_mapping_table (letter, color) values ('A', 'Green');
insert into my_mapping_table (letter, color) values ('C', 'Blue');
insert into my_mapping_table (letter, color) values ('F', 'Red');
create table my_logging_table (rid number, foo number, bar varchar2(10),
letter varchar2(1), color varchar2(10));
create sequence mysequence;
insert into my_logging_table(rid, letter, color)
select mySequence.nextval, letter, color from my_mapping_table;
select * from my_logging_table;
RID FOO BAR L COLOR
---------- ---------- ---------- - ----------
1 N Yellow
2 P Orange
3 Q Violet
4 A Green
5 C Blue
6 F Red
You would get that error if you were using the insert all
syntax, which doesn't allow sequence references:
insert all into my_logging_table(rid, letter, color)
select mySequence.nextval, letter, color from my_mapping_table;
Error report -
SQL Error: ORA-02287: sequence number not allowed here
02287. 00000 - "sequence number not allowed here"
*Cause: The specified sequence number (CURRVAL or NEXTVAL) is inappropriate
here in the statement.
*Action: Remove the sequence number.
You'd also see this if your query had a group by
clause, or an order by
clause, or various other things; none of which you've shown.
An order by
may be most likely if you tested the query separately. Applying any order to the generated ID doesn't really make any sense, but if you did want to for some reason (perhaps based on a timestamp) then you'd need to use a subquery and refer to the sequence in the outer query:
insert into my_logging_table(rid, letter, color)
select mySequence.nextval, letter, color from (
select letter, color from my_mapping_table
order by letter
);
select * from my_logging_table;
RID FOO BAR L COLOR
---------- ---------- ---------- - ----------
1 A Green
2 C Blue
3 F Red
4 N Yellow
5 P Orange
6 Q Violet
With a synthetic key that doesn't seem useful though. (And I'm not sure it's technically guaranteed that the order would be preserved; mostly a real-world issue with parallel processing).
You could also use @Artbaji's approach with an order by
in the over()
clause, but then you'd need to make sure your sequence was incremented past the values that generated.
Oracle: Insert Rows from Select with New Sequence IDs
First create a query that will display the rows you want:
SELECT
Id,
col1, col2, col3, ....., colN
FROM table
WHERE /* the condition which selects rows you want */
id >= 6 AND id <= 10
then replace ID
column with TABLE_SEQUENCE.NEXTVAL
and prepend the whole query with INSTERT
statement:
INSERT INTO table( Id, col1, col2, col3, ....., colN )
SELECT
TABLE_SEQUENCE.NEXTVAL,
col1, col2, col3, ....., colN
FROM table
WHERE /* the condition which selects rows you want */
id >= 6 AND id <= 10
Inserting multiple rows with sequence in Oracle
The restrictions on multitable inserts include:
- You cannot specify a sequence in any part of a multitable insert statement. A multitable insert is considered a single SQL statement. Therefore, the first reference to NEXTVAL generates the next number, and all subsequent references in the statement return the same number.
That isn't quite true - you can use a sequence, it just always gets the same value, so it can be useful to create parent and child records in one go by referring to the same sequence.
If you want to continue to use insert all
you could work around that by using a non-deterministic function that gets the sequence value:
CREATE FUNCTION get_seq RETURN NUMBER IS
BEGIN
RETURN postal_code_seq.nextval;
END;
/
INSERT ALL
INTO POSTAL_CODE( postal_code,description)
VALUES(get_seq,'Coimbatore')
INTO POSTAL_CODE (postal_code,description)
VALUES(get_seq,'Mumbai') SELECT * FROM DUAL;
2 rows inserted.
SELECT * FROM postal_code;
POSTAL_CODE DESCRIPTION
--------------------------------------- --------------------
1 Coimbatore
2 Mumbai
But that's a bit awkward. You're probably better off using individual insert statements - using a multitable insert into a single table isn't really gaining you much anyway - or a trigger to set the unique column from the sequence, or a CTE/inline view to generate the values to insert.
Related Topics
How to Add Time to Datetime in SQL
Export from SQL Server 2012 to .CSV Through Management Studio
SQL Server 2008 Query to Find Rows Containing Non-Alphanumeric Characters in a Column
After Installing SQL Server 2014 Express Can't Find Local Db
How to Write Subquery Inside the Outer Join Statement
Ora-01843 Not a Valid Month- Comparing Dates
Find SQL Table Name with a Particular Column
SQL Using If Not Null on a Concatenation
What Are the Main Differences Between Option(Optimize for Unknown) and Option(Recompile)
Using MySQL in Clause as All Inclusive (And Instead of Or)
To Find Infinite Recursive Loop in Cte
Inserting Image into Blob Oracle 10G
How to Use Inno Setup to Update a Database Using .SQL Script
Speed of Paged Queries in Oracle
How to Run a SQL Plus Script in Powershell
SQL Server Filestream Limitation
Alter Database Failed Because a Lock Could Not Be Placed on Database