【问题标题】:Oracle SQL: Insert selected values as well as next value from sequenceOracle SQL:插入选定的值以及序列中的下一个值
【发布时间】:2016-04-21 14:51:40
【问题描述】:

我正在使用 Oracle Database 11g、PL/SQL 和 SQL 开发人员。

这看起来很简单,但它似乎不像我想的那样工作......

假设我有一些任意的映射表,比如:

+--------+--------+
| Letter | Color  |
+--------+--------+
| N      | Yellow |
+--------+--------+
| P      | Orange |
+--------+--------+
| Q      | Violet |
+--------+--------+
| A      | Green  |
+--------+--------+
| C      | Blue   |
+--------+--------+
| F      | Red    |
+--------+--------+ 

我创建了一个空白的日志记录表,以跟踪此映射表随时间的变化。

目前这个日志表是空的,我想用数据初始化它,让它看起来像这样:

+-----+------+-------+--------+--------+
| RID | blah | blahh | Letter | Color  |
+-----+------+-------+--------+--------+
| 1   |      |       | N      | Yellow |
+-----+------+-------+--------+--------+
| 2   |      |       | P      | Orange |
+-----+------+-------+--------+--------+
| 3   |      |       | Q      | Violet |
+-----+------+-------+--------+--------+
| 4   |      |       | A      | Green  |
+-----+------+-------+--------+--------+
| 5   |      |       | C      | Blue   |
+-----+------+-------+--------+--------+
| 6   |      |       | F      | Red    |
+-----+------+-------+--------+--------+ 

我知道我能做到:

INSERT INTO my_logging_table(LETTER, COLOR)
SELECT letter, color FROM my_mapping_table; 

但是如果 RID 是一个不可为空的值,那么我需要将它插入到选定的颜色/字母值旁边怎么办? (比如说,我不能只是放弃约束)

这样的事情给了我ORA-00926: missing VALUES keyword

INSERT INTO my_logging_table(rid, letter, color)
mysequence.nextval, SELECT letter, color, FROM my_mapping_table; 

这给了我ORA-00947: Not enough values

insert into my_logging_table(rid, letter, color)  
values mySequence.nextval, select letter, color from my_mapping_table; 

最后这个方法给了我:ORA-02287: sequence number not allowed here:

insert into my_logging_table(rid, letter, color)  
select mySequence.nextval, letter, color from my_mapping_table; 

这样做的正确方法是什么?

基本上,我如何进行包含一些选定值和一些静态或序列值的插入?

【问题讨论】:

  • 第三种方法应该有效。
  • 描述日志表
  • 第三种(最终)方法应该有效。您是否运行select mySequence.nextval from dual; 来检查您的序列是否已启动?

标签: sql oracle oracle11g


【解决方案1】:

您的第三种方法是正确的,并且有效(列名一致):

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       

如果您使用不允许序列引用的 insert all 语法,则会收到该错误:

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.

如果您的查询有group by 子句、order by 子句或其他各种内容,您也会看到这一点;你都没有展示过。

如果您单独测试查询,则很可能是order by。将任何顺序应用于生成的 ID 并没有任何意义,但如果您出于某种原因(可能基于时间戳)确实想要这样做,那么您需要使用子查询并引用外部查询中的序列:

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    

虽然合成密钥似乎没有用。 (而且我不确定从技术上保证订单会被保留;主要是并行处理的实际问题)。

您也可以在over() 子句中使用@Artbaji 的方法和order by,但随后您需要确保您的序列的增量超过了生成的值。

【讨论】:

  • 我仍然不确定为什么昨天它对我不起作用,但现在它正在起作用,并且可能会避免与我一样的困惑 - 谢谢!
【解决方案2】:
INSERT INTO my_logging_table(rid, letter, colour)
select row_number() over(), letter, color from my_mapping_table; 

希望这会有所帮助。

【讨论】:

  • 使用将用于未来插入的序列更简单;否则您必须(重新)创建序列以从您手动插入的值开始。
猜你喜欢
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多