简体   繁体   English

Oracle 是否允许 SQL INSERT INTO 如果目标表具有 GENERATE ID ALWAYS AS

[英]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

db<>fiddle demo db<>小提琴演示

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 *不会看到它 - 但是你不应该依赖*无论如何。

db<>fiddle db<>小提琴

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Oracle SQL:如何在具有IDENTITY列的表上使用GROUP BY子句插入SELECT语句? - Oracle SQL: How to INSERT a SELECT statement with a GROUP BY clause on a table with IDENTITY column? 将语句插入具有标识列的表中的SQL语句? - SQL statement to insert record into table that has identity column? SQL 服务器 / Oracle:从 select 语句为非标识列插入值(插入…值((选择语句)、值 1、值 2、值 3) - SQL Server / Oracle : insert value from a select statement for an non-identity column (Insert into…values((select statement), value1, value2, value3) Oracle SQL 目标表为空时合并不插入 - Oracle SQL merge does not insert when the destination table is empty 为什么插入具有主键/标识列的表时会生成“列名或提供的值数与表定义不匹配”错误 - Why does insert into table with primary key/identity column generate “Column name or number of supplied values does not match table definition” error 使用SQL Server中的标识列为INSERT语句指定“ NEXT VALUE” - Specify “NEXT VALUE” for INSERT statement using identity column in SQL Server SQL(SQL/Oracle) 使用序列从选择语句插入值 - SQL(SQL/Oracle) insert value from a select statement using sequence 处理“插入表Values()”语句中的标识列? - Handling identity columns in an “Insert Into TABLE Values()” statement? 如何使用SQL语句将一个表的一行中的值插入到另一个表的列中 - how to insert values in a row of one table into the column of another table using SQL statement 使用SQL OUTPUT将INSERT插入具有Identity(或默认值)的表中 - Using SQL OUTPUT for INSERT into a table with Identity (or default values)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM