num*_*er5 2 sql firebird select insert firebird2.5
我是火鸟的新手,我有很多问题.我想在从另一个表中选择的表中插入各种行.
这是代码:
/*CREATE GENERATOR POS; */
SET GENERATOR POS TO 1;
SET TERM ^;
create trigger BAS_pkassign
for MATERIAL
active before insert position 66
EXECUTE BLOCK
AS
declare posid bigint;
select gen_id(POS, 1)
from RDB$DATABASE
into :posid;
BEGIN
END
SET TERM ; ^
INSERT INTO MATERIAL ( /*ID */ LOCATION, POSID, ARTID, ARTIDCONT, QUANTITY )
SELECT 1000, ':posid', 309, BAS_ART.ID, 1
FROM BAS_ART
WHERE BAS_ART.ARTCATEGORY LIKE '%MyWord%'
Run Code Online (Sandbox Code Playgroud)
ID应该从66开始自动增量.posid应该从1开始自动增量.
实际上它没有插入任何东西.
我正在使用Firebird Maestro并刚刚打开了SQL脚本编辑器(在执行脚本时不会抛出任何错误消息).
有谁能够帮我?
谢谢!
附加信息:
触发器应该自动增加列"ID" - 但我不知道我怎么能改变它所以它工作..':posid'使用它抛出一个错误:posid但是像这样没有错误(我猜它被解释为一个串).但是我该如何使用呢?
我执行它时不会出错.表结构很简单.我有2张桌子:1.
Material (
ID (INTEGER),
Location (INTEGER),
POSID (INTEGER),
ARTID (INTEGER),
ARTIDCONT (INTEGER),
QUANTITY (INTEGER),
OTHERCOLUMN (INTEGER))
Run Code Online (Sandbox Code Playgroud)
和2.另一张桌子
BAS_ART (ID (INTEGER), ARTCATEGORY (VARCHAR255))
Run Code Online (Sandbox Code Playgroud)
- >我想将表BAS_ART中包含"MyWord"的所有条目插入到MATERIAL表中,其中包含ARTCATEGORY列中的"MyWord".
对于我的大部分回答,我将假设一个非常简单的表格:
CREATE TABLE MyTable (
ID BIGINT PRIMARY KEY,
SomeValue VARCHAR(255),
posid INTEGER
)
Run Code Online (Sandbox Code Playgroud)
Firebird(最高版本 2.5)没有标识列类型(这将在 Firebird 3 中添加),而是需要使用序列(又名生成器)和触发器来获取它。
首先,您需要使用以下命令创建一个序列CREATE SEQUENCE:
CREATE SEQUENCE seqMyTable
Run Code Online (Sandbox Code Playgroud)
序列是原子的,这意味着交错事务/连接不会获得重复的值,它也在事务控制之外,这意味着 aROLLBACK不会恢复到以前的值。在大多数用途中,序列应该始终增加,因此您在问题开始时所做的值重置几乎对于所有目的都是错误的;例如,另一个连接也可能在执行过程中重置序列,从而导致意外的POSID.
要生成自动增量标识符的值,您需要使用将BEFORE INSERT TRIGGER生成的值分配给 - 在本例中 -ID列。
CREATE TRIGGER trgMyTableAutoIncrement FOR MyTable
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
NEW.ID = NEXT VALUE FOR seqMyTable;
END
Run Code Online (Sandbox Code Playgroud)
在此示例中,我始终分配生成值,其他示例ID仅在is时分配生成值NULL。
要获取生成的值,您可以使用RETURNING-语句的INSERT- 子句:
INSERT INTO MyTable (SomeValue) VALUES ('abc') RETURNING ID
Run Code Online (Sandbox Code Playgroud)
使用INSERT INTO ... SELECT您可以从一个表中选择行并将它们插入到其他表中。它对您不起作用的原因是您试图将字符串值分配':pos'给 type 的列INTEGER,而这是不允许的。
假设我有另一个MyOtherTable具有类似结构的表MyTable,我可以使用以下方式传输值:
INSERT INTO MyTable (SomeValue)
SELECT SomeOtherValue
FROM MyOtherTable
Run Code Online (Sandbox Code Playgroud)
INSERT INTO ... SELECT除非只插入单行,否则无法使用它获取生成的值(Firebird 5.0 将引入多行RETURNING支持)。
POSID我不清楚它POSID应该是什么,以及它应该具有什么价值。看起来您希望单个 的值从 1 开始递增INSERT INTO ... SELECT。在 Firebird 2.5 之前的版本中,这种方式是不可能的(在 Firebird 3 中您可以使用ROW_NUMBER()这种方式)。
如果我的猜测是正确的,那么您将需要使用EXECUTE BLOCK(或存储过程)来分配和增加要插入的每一行的值。
执行块类似于:
EXECUTE BLOCK
AS
DECLARE posid INTEGER = 1;
DECLARE someothervalue VARCHAR(255);
BEGIN
FOR SELECT SomeOtherValue FROM MyOtherTable INTO :someothervalue DO
BEGIN
INSERT INTO MyTable (SomeValue, posid) VALUES (:someothervalue, :posid);
posid = posid + 1;
END
END
Run Code Online (Sandbox Code Playgroud)
如果没有posid 的ORDER BY值SELECT,本质上是没有意义的,因为没有保证顺序。
我不明白为什么你需要触发器.
这个问题:
我想将包含"MyWord"的表BAS_ART中的所有条目插入到MATERIAL表中
可以用一个insert ... select语句来解决.
insert into material (id, location, posid, artid, quantity)
select next value for seq_mat_id, 1000, next value for seq_pos, id, 1
from bas_art
where artcategory = 'My Word';
Run Code Online (Sandbox Code Playgroud)
这假定存在第二个序列(也称为"生成器"),其被命名seq_mat_id为列提供新的idmaterial.id
| 归档时间: |
|
| 查看次数: |
25886 次 |
| 最近记录: |