Oracle 插入选择不给出 GROUP BY 表达式
Posted
技术标签:
【中文标题】Oracle 插入选择不给出 GROUP BY 表达式【英文标题】:Oracle insert select gives not a GROUP BY expression 【发布时间】:2020-10-28 14:51:06 【问题描述】:编辑:数据库版本是 Oracle 12c
我有两个表,SRC 和 DEST,我想统计 SRC 中每个 id 的记录并将结果插入到 DEST。
这些表是使用以下脚本创建的:
CREATE SEQUENCE "ID_SEQ" INCREMENT BY 1 MAXVALUE 99999 MINVALUE 1 CACHE 20 NOORDER NOCYCLE;
CREATE TABLE "SRC_TABLE"
(
"S_ID" NUMBER(10,0) NOT NULL,
"SEQ" NUMBER(10,0) NOT NULL,
"VALUE" VARCHAR2(1) NOT NULL
);
CREATE TABLE "DEST_TABLE"
(
"D_ID" NUMBER(10,0) DEFAULT ID_SEQ.NEXTVAL NOT NULL,
"S_ID" NUMBER(10,0),
"CNT" VARCHAR2(1) NOT NULL,
"PROCESS_PROG" VARCHAR2(50) NOT NULL
);
INSERT INTO SRC_TABLE VALUES (1, 1, '1');
INSERT INTO SRC_TABLE VALUES (1, 2, '1');
INSERT INTO SRC_TABLE VALUES (1, 3, '1');
INSERT INTO SRC_TABLE VALUES (2, 1, '2');
INSERT INTO SRC_TABLE VALUES (2, 2, '2');
INSERT INTO SRC_TABLE VALUES (2, 3, '2');
当我执行以下脚本时,它导致了“ORA-00979: not a GROUP BY expression”错误:
DECLARE
PROG_NAME VARCHAR2(50) := 'DEMO';
BEGIN
INSERT INTO DEST_TABLE (S_ID, CNT, PROCESS_PROG)
SELECT S_ID, COUNT(*), PROG_NAME FROM SRC_TABLE
GROUP BY S_ID;
END;
经过一些测试,我发现如果我将 PROG_NAME 替换为字符串,则脚本可以正常工作。
DECLARE
PROG_NAME VARCHAR2(50) := 'DEMO';
BEGIN
INSERT INTO DEST_TABLE (S_ID, CNT, PROCESS_PROG)
SELECT S_ID, COUNT(*), 'DEMO' FROM SRC_TABLE
GROUP BY S_ID;
END;
或者,如果我明确选择 D_ID 列的值而不是依赖于 DEFAULT 值,它也可以:
DECLARE
PROG_NAME VARCHAR2(50) := 'DEMO';
BEGIN
INSERT INTO DEST_TABLE (D_ID, S_ID, CNT, PROCESS_PROG)
SELECT ID_SEQ.NEXTVAL, TMP.* FROM (
SELECT S_ID, COUNT(*), PROG_NAME FROM SRC_TABLE
GROUP BY S_ID
) TMP;
END;
我不知道为什么第一个脚本失败,但其他两个脚本有效。我做错了什么?
【问题讨论】:
【参考方案1】:这是失败的陈述(根据你所说的):
SELECT S_ID, COUNT(*), PROG_NAME FROM SRC_TABLE
GROUP BY S_ID;
当查询中存在聚合时(在您的示例中为 count(*)
),则 select
列列表中包含的所有其他未聚合的列必须包含在 group by
子句中。
那一栏是S_ID
; PROG_NAME
是一个局部变量,不必放入 group by
子句中。
那么,为什么您的代码失败了?不知道,因为它对我来说很好用:
SQL> DECLARE
2 PROG_NAME VARCHAR2(50) := 'DEMO';
3 BEGIN
4 INSERT INTO DEST_TABLE (S_ID, CNT, PROCESS_PROG)
5 SELECT S_ID, COUNT(*), PROG_NAME FROM SRC_TABLE
6 GROUP BY S_ID;
7 END;
8 /
PL/SQL procedure successfully completed.
SQL> select * from dest_table;
D_ID S_ID C PROCESS_PROG
---------- ---------- - ----------------------------------------
1 1 3 DEMO
2 2 3 DEMO
SQL>
你确定它失败了吗?您能否通过发布您自己的 SQL*Plus 会话来演示它(就像我所做的那样)?
【讨论】:
有趣。这在 dbfiddle 中的 Oracle 18 中失败了:dbfiddle.uk/… 奇怪的是,如果我在DEST_TABLE
中注释掉D_ID
列上的DEFAUT ID_SEQ.NEXTVAL
子句,错误就会消失...:dbfiddle.uk/…
@GMB:因为它在 11g 中不起作用,所以我使用了数据库触发器。那么,也许它是 DEFAULT 列值,但是 - 为什么?它与 GROUP BY 有什么关系?
完全正确:为什么?!没有任何意义。以上是关于Oracle 插入选择不给出 GROUP BY 表达式的主要内容,如果未能解决你的问题,请参考以下文章
oracle 中 select 多字段 ,但是只group by 其中某些字段
如何解决 Oracle Apex 中的“无法使用 DISTINCT、GROUP BY 等从视图中选择 FOR UPDATE”错误?