[英]Does Oracle allow an SQL INSERT INTO using a SELECT statement for VALUES if the destination table has an GENERATE ALWAYS AS IDENTITY COLUMN
I am trying to insert rows into an Oracle 19c table that we recently added a GENERATED ALWAYS AS IDENTITY column (column name is "ID").我正在尝试将行插入到 Oracle 19c 表中,我们最近添加了 GENERATED ALWAYS AS IDENTITY 列(列名为“ID”)。 The column should auto-increment and not need to be specified explicitly in an INSERT statement.
该列应该自动递增,并且不需要在 INSERT 语句中显式指定。 Typical INSERT statements work - ie INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2').
典型的 INSERT 语句起作用 - 即 INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2')。 (merely an example).
(只是一个例子)。 The ID field increments when typical INSERT is executed.
当执行典型的 INSERT 时,ID 字段会增加。 But the query below, that was working before the addition of the IDENTITY COLUMN, is now not working and returning the error: ORA-00947: not enough values.
但是下面的查询,在添加 IDENTITY COLUMN 之前工作,现在不工作并返回错误:ORA-00947:没有足够的值。
The field counts are identical with the exception of not including the new ID IDENTITY field, which I am expecting to auto-increment.除了不包括我希望自动递增的新 ID IDENTITY 字段之外,字段计数相同。 Is this statement not allowed with an IDENTITY column?
IDENTITY 列是否不允许使用此语句?
Is the INSERT INTO statement, using a SELECT from another table, not allowing this and producing the error? INSERT INTO 语句是否使用另一个表中的 SELECT 不允许这样做并产生错误?
INSERT INTO T.AUDIT
(SELECT r.IDENTIFIER, r.SERIAL, r.NODE, r.NODEALIAS, r.MANAGER, r.AGENT, r.ALERTGROUP,
r.ALERTKEY, r.SEVERITY, r.SUMMARY, r.LASTMODIFIED, r.FIRSTOCCURRENCE, r.LASTOCCURRENCE,
r.POLL, r.TYPE, r.TALLY, r.CLASS, r.LOCATION, r.OWNERUID, r.OWNERGID, r.ACKNOWLEDGED,
r.EVENTID, r.DELETEDAT, r.ORIGINALSEVERITY, r.CATEGORY, r.SITEID, r.SITENAME, r.DURATION,
r.ACTIVECLEARCHANGE, r.NETWORK, r.EXTENDEDATTR, r.SERVERNAME, r.SERVERSERIAL, r.PROBESUBSECONDID
FROM R.STATUS r
JOIN
(SELECT SERVERSERIAL, MAX(LASTOCCURRENCE) as maxlast
FROM T.AUDIT
GROUP BY SERVERSERIAL) gla
ON r.SERVERSERIAL = gla.SERVERSERIAL
WHERE (r.LASTOCCURRENCE > SYSDATE - (1/1440)*5 AND gla.maxlast < r.LASTOCCURRENCE)
) )
Thanks for any help.谢谢你的帮助。
Yes, it does;是的,它确实; your example insert
你的示例插入
INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2')
would also work as也可以作为
INSERT INTO table_name (field1,field2) SELECT 'f1', 'f2' FROM DUAL
Your problematic real insert statement is not specifying the target column list, so when it used to work it was relying on the columns in the table (and their data types) matching the results of the query.您有问题的实际插入语句没有指定目标列列表,因此当它过去工作时,它依赖于与查询结果匹配的表中的列(及其数据类型)。 (This is similar to relying on
select *
, and potentially problematic for some of the same reasons.) (这类似于依赖
select *
,并且由于某些相同的原因可能存在问题。)
Your query selects 34 values, so your table had 34 columns.您的查询选择了 34 个值,因此您的表有 34 列。 You have now added a 35th column to the table, your new ID column.
您现在已经向表中添加了第 35 列,即您的新 ID 列。 You know that you don't want to insert directly into that column, but in general Oracle doesn't, at least at the point it's comparing the query with the table columns.
您知道您不想直接插入该列,但通常 Oracle 不会,至少在将查询与表列进行比较时。 The table has 35 columns, so as you haven't said otherwise as part of the statement, it is expecting 35 values in the select list.
该表有 35 列,因此作为语句的一部分,您没有另外说明,它预计 select 列表中有 35 个值。
There's no way for Oracle to know which of the 35 columns you're skipping. Oracle 无法知道您跳过了 35 列中的哪一列。 Arguably it could guess based on the identity column, but that would be more work and inconsistent, and it's not unreasonable for it to insist you do the work to make sure it's right.
可以说它可以根据身份列进行猜测,但这会更加工作且不一致,并且坚持你做工作以确保它是正确的并不是没有道理的。 It's expecting 35 values, it sees 34, so it throws an error saying there are not enough values - which is true.
它期待 35 个值,它看到 34,所以它抛出一个错误,说没有足够的值 - 这是真的。
Your question sort of implies you think Oracle might be doing something special to prevent the insert... select...
syntax if there is an identity column, but in facts it's the opposite - it isn't doing anything special, and it's reporting the column/value count mismatch as it usually would.您的问题有点暗示您认为 Oracle 可能正在做一些特殊的事情来防止
insert... select...
语法如果有一个身份列,但实际上情况恰恰相反 - 它没有做任何特别的事情,它正在报告列/值计数不匹配,因为它通常会。
So, you have to list the columns you are populating - you can't automatically skip one.所以,你必须列出你正在填充的列——你不能自动跳过一个。 So you statement needs to be:
所以你的陈述需要是:
INSERT INTO T.AUDIT (IDENTIFIER, SERIAL, NODE, ..., PROBESUBSECONDID)
SELECT r.IDENTIFIER, r.SERIAL, r.NODE, ..., r.PROBESUBSECONDID
FROM ...
using the actual column names of course if they differ from the query column names.如果它们与查询列名不同,当然使用实际的列名。
If you can't change that insert statement then you could make the ID column invisible;如果您无法更改该插入语句,那么您可以使 ID 列不可见; but then you would have to specify it explicitly in queries, as
select *
won't see it - but then you shouldn't rely on *
anyway.但是你必须在查询中明确指定它,因为
select *
不会看到它 - 但是你不应该依赖*
无论如何。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.