对插入选择的限制

下列列表包含对插入行的 SELECT 语句的限制:
  • 它不可包含 INTO 子句。
  • 它不可包含 INTO TEMP 子句。
  • 它不可包含 ORDER BY 子句。
  • 它不可引用您正在向其内插入行的表。
INTO、INTO TEMP 和 ORDER BY 子句限制较小。在此上下文中,INTO 子句没什么用处。(要获取更多信息,请参阅 SQL 编程。)要绕开 INTO TEMP 子句限制,请先选择您想要插入到临时表内的数据,然后使用 INSERT 语句从临时表插入该数据。同样,缺少 ORDER BY 子句也无关紧要。如果您需要确保这些新行在表中物理地排序,则您可首先将它们选择到临时表内并对它排序,然后从该临时表插入。在所有插入完成之后,您还可使用集群的索引来对该表进行物理排序。
重要: 最后一个限制更为严重,因为它同时阻止在 INSERT 语句的 INTO 子句与 SELECT 语句的 FROM 子句中命名同一个表。同时在 INSERT 语句的 INTO 子句与 SELECT 语句的 FROM 子句中命名同一个表,导致数据库服务器进入无限循环,每一插入了的行都会在其中被重新选择和重新插入。

然而,在某些情况下,您可能想要从您必须向其内插入数据的同一个表进行选择。例如,假设您已了解 Nikolus 公司与 Anza 公司供应相同的产品,但仅以一半的价格供应。您想要向 stock 表添加一些行来反映两家公司之间的差异。理想情况下,您想要从所有 Anza 库存行选择数据,并使用 Nikolus 制造商代码重新插入它。然而,您不可从您正在向其内插入的同一个表进行选择。

要避开此限制,请选择您想要插入到临时表内的数据。然后在 INSERT 语句中从那个临时表进行选择,如下例所示:
SELECT stock_num, 'NIK' temp_manu, description, unit_price/2
          half_price, unit,  unit_descr FROM stock
          WHERE manu_code = 'ANZ'
          AND stock_num < 110
          INTO TEMP anzrows;
          
          INSERT INTO stock SELECT * FROM anzrows;
          
          DROP TABLE anzrows; 

此 SELECT 语句从 stock 得到现有的行,并替换制造商代码的文字值以及单价的计算得到的值。然后将这些行保存在临时表 anzrows 中,立即将该表插入到 stock 表内。

当您插入多个行时,存在一种风险:其中一行包含无效的数据,就可能导致数据库服务器报告一个错误。当发生这样一个错误时,该语句提早终止。即使未发生错误,也存在一个小风险:在执行该语句时可能发生硬件或软件故障(例如,磁盘可能写满)。

在任何一种事件中,您都不可轻易地知道插入了多少新行。如果全部重复该语句,则您可能创建重复的行,也可能不会。由于数据库处于未知状态,因此您无所适从。解决方案在于使用事务,如 中断了的修改 讨论的那样。