Sql 使用update或insert语句添加到整数值

Sql 使用update或insert语句添加到整数值,sql,firebird,firebird2.5,Sql,Firebird,Firebird2.5,我试图在Firebird 2.5中创建一个SQL语句,以便通过添加到整数数量(如果记录存在)或简单地插入新行来更新整数数量。我似乎找不到一个真正的答案来回答我关于增加一定数量的问题,如果它已经存在的话 我能想到的SQL如下所示: UPDATE OR INSERT INTO Pencils(Number, Location, Quantity) VALUES('12345678/90', 'TOP', 20) MATCHING(Number, Location); 因此,如果有一个匹配的记录,我

我试图在Firebird 2.5中创建一个SQL语句,以便通过添加到整数数量(如果记录存在)或简单地插入新行来更新整数数量。我似乎找不到一个真正的答案来回答我关于增加一定数量的问题,如果它已经存在的话

我能想到的SQL如下所示:

UPDATE OR INSERT INTO Pencils(Number, Location, Quantity)
VALUES('12345678/90', 'TOP', 20)
MATCHING(Number, Location);
因此,如果有一个匹配的记录,我想在实际的20个数量上加上一定的数量

就像我对
UPDATE
语句所做的那样:

UPDATE Pencils SET Quantity = Quantity + 20 WHERE Number = '12345678/90' 
使用
UPDATE或INSERT
语句是否可以获得这样的结果,或者是否有其他方法? .

编辑: 用IBExpert/Delphi解决参数查询

MERGE INTO Pencils AS Dest
USING (SELECT CAST(:myNumb as varchar(30))  AS Number,
              CAST(:myLoca as varchar(10))  AS Location,
              CAST(:myQuan as integer)  AS Quantity
        FROM RDB$DATABASE) Src
    ON (Dest.Number = Src.Number AND Dest.Location = Src.Location)
WHEN MATCHED THEN
   UPDATE SET Dest.Quantity = Dest.Quantity + Src.Quantity
WHEN NOT MATCHED THEN
   INSERT (Number, Location, Quantity) VALUES (Src.Number, Src.Location, Src.Quantity);
将Firebird's用于复杂的上部结构:

MERGE INTO Pencils AS Dest
USING (SELECT '12345678/90' AS Number,
              'TOP'         AS Location,
              20            As Quantity
         FROM RDB$DATABASE) Src
   ON (Dest.Number = Src.Number AND Dest.Location = Src.Location)
WHEN MATCHED THEN
   UPDATE SET Dest.Quantity = Dest.Quantity + 10
WHEN NOT MATCHED THEN
   INSERT (Number, Location, Quantity) VALUES (Src.Number, Src.Location, Src.Quantity);
这里唯一的复杂性是更新时动态计算的
数量。如果只是用静态值覆盖现有记录,则可以更简洁地使用

示例:

SQL> SELECT * FROM Pencils;

NUMBER               QUANTITY LOCATION         
================ ============ ================ 
123                         5 TOP              
123                        10 MID              

SQL> MERGE INTO Pencils AS Dest
CON> USING (SELECT '123' AS Number, 'TOP' AS Location, 20 As Quantity
CON> FROM RDB$DATABASE) Src ON (Dest.Number = Src.Number AND Dest.Location = Src.Location)
CON> WHEN MATCHED THEN
CON>    UPDATE SET Dest.Quantity = Dest.Quantity + 10
CON> WHEN NOT MATCHED THEN
CON>    INSERT (Number, Location, Quantity) VALUES (Src.Number, Src.Location, Src.Quantity);

SQL> SELECT * FROM Pencils;

NUMBER               QUANTITY LOCATION         
================ ============ ================ 
123                        15 TOP              
123                        10 MID              

SQL> SELECT * FROM Pencils;

NUMBER               QUANTITY LOCATION         
================ ============ ================ 
123                         5 TOP              
123                        10 MID              

SQL> MERGE INTO Pencils AS Dest
CON> USING (SELECT '123' AS Number, 'TOP' AS Location, 20 As Quantity
CON> FROM RDB$DATABASE) Src ON (Dest.Number = Src.Number AND Dest.Location = Src.Location)
CON> WHEN MATCHED THEN
CON>    UPDATE SET Dest.Quantity = Dest.Quantity + 10
CON> WHEN NOT MATCHED THEN
CON>    INSERT (Number, Location, Quantity) VALUES (Src.Number, Src.Location, Src.Quantity);

SQL> SELECT * FROM Pencils;

NUMBER               QUANTITY LOCATION         
================ ============ ================ 
123                        15 TOP              
123                        10 MID              
123                        20 BOT       

确保可以使用“更新”或“插入”。 但您必须重复您的键值,这会使您的查询变得脆弱(只更改两个值中的一个-并且您得到了行为不端的查询)

在Delphi中,大多数库都不支持同名的多个SQL参数,因此您可能需要实际创建两个参数(名称相似但清晰),才能使这种方法起作用

所以,总而言之,
MERGE
将是更好、更安全的方法。但为了完整性,这也应该起作用


如果我正确理解你的陈述,如果记录不存在,它将插入20作为数量,但它应该插入10(10是一个dnymic值,我将从Delphi程序获得,它将是要插入的数量)@VirusInside然后将语句更改为使用10而不是20。但是我认为Firebird不允许在使用中使用SELECT WITH FROMstatement@virussinside坦率地说,这是一个不同的问题,一个人可能回答了数百万次。这是在准备查询时的母鸡和鸡蛋问题,FB在知道数据类型并完成输出行集的二进制缓冲区布局之前无法开始准备,并且在开始准备之前无法推断未知数据类型。因此,您应该在之前硬编码参数数据类型<代码>选择?从RDB$DATABASE
通常会失败,但从RDB$DATABASE选择强制转换(?as integer)将起作用。打它的荣誉。我在埋伏中等待,想知道你是否在没有参数的情况下偷懒。此外,Firebird中没有像
varchar
这样的数据类型!您必须指定长度为了完整性,您是否可以显示更新或插入,其中新插入的数量不是简单的“零+增量”?根据澄清意见,我认为OP确实希望新记录默认为“零+增量”,但书面问题是“20表示新记录”和“数量+=10表示更新”。这将是一个不同的UP或IN,可能对某些人也有用。@pilcrow确切地说,我只有一个数量,例如20,如果找不到数量和位置,我希望有一个新的记录,或者简单地将这些相同的20添加到现有数量中。所以它是'zero+newQuantity'或'oldQuantity+=newQuantity'哦,我明白了,我没有想到COALESCE,但你是对的,对于同一个值有不同的参数是非常脆弱的。谢谢你的帮助。@pilcrow完成了,但我不在个人电脑自动取款机上,所以实际上没有试过。可能有次要语法errors@Arioch与我上一次对答案的评论相同的问题是,是否有可能用参数(如:myNumber、:MyLocation)来替换我们在SELECT中输入的静态值。对于total freaks,还有另一种古老的方法可以做到这一点,它早于MERGE、U-O-I甚至Firebird本身。它需要创建可更新视图,其中U/I/D操作由
触发器中的PSQL代码实现,然后在插入之前
触发器将检查基础表中是否已经有行或没有行。但这将是一台鲁布·戈德伯格的机器。。。像Delphi XE2:-D一样可爱迷人
UPDATE OR INSERT 
   INTO Pencils(Number, Location, Quantity)
VALUES( '12345678/90', 'TOP', 
  20 + coalesce(
        ( Select Quantity 
             From Pencils 
          where Number = '12345678/90' 
            and Location = 'TOP' )
       ,0 )
       )
MATCHING(Number, Location);
select rdb$get_context('SYSTEM', 'ENGINE_VERSION') as version
     , rdb$character_set_name
from rdb$database;
VERSION | RDB$CHARACTER_SET_NAME :------ | :--------------------------------------------------------------------------------------------------------------------------- 3.0.5 | UTF8
create table Pencils( Number varchar(20), Location varchar(10), Quantity int,
   constraint pk_pens primary key (number, location) )
INSERT INTO Pencils(Number, Location, Quantity)
VALUES('12345678/90', 'TOP', 13)
1 rows affected

INSERT INTO Pencils(Number, Location, Quantity)
VALUES('12345678/90', 'MID', 7)
1 rows affected

select * from pencils
NUMBER | LOCATION | QUANTITY :---------- | :------- | -------: 12345678/90 | TOP | 13 12345678/90 | MID | 7
UPDATE OR INSERT 
   INTO Pencils(Number, Location, Quantity)
VALUES( '12345678/90', 'TOP', 
  20 + coalesce(
          (Select Quantity 
             From Pencils 
          where Number = '12345678/90' 
            and Location = 'TOP')
       ,0 )
       )
MATCHING(Number, Location);
1 rows affected

UPDATE OR INSERT 
   INTO Pencils(Number, Location, Quantity)
VALUES( '12345678/90', 'BOTTOM', 
  20 + coalesce(
          (Select Quantity 
             From Pencils 
          where Number = '12345678/90' 
            and Location = 'BOTTOM')
       ,0 )
       )
MATCHING(Number, Location);
1 rows affected

select * from pencils
NUMBER | LOCATION | QUANTITY :---------- | :------- | -------: 12345678/90 | TOP | 33 12345678/90 | MID | 7 12345678/90 | BOTTOM | 20
.........
VALUES( '12345678/90', 'TOP', 
  coalesce( 20 + -- increment when found
        ( Select Quantity 
             From Pencils 
          where Number = '12345678/90' 
            and Location = 'TOP' )
       ,  -15 /* new value when not found */ )
       )
.......