在多个结果上不存在SQL插入

本文关键字:不存在 SQL 插入 结果 | 更新日期: 2023-09-27 18:14:57

我有一个与Price表有一对多关系的Plan表。(一个计划可以有多个价格)

然而,问题是我有另一个名为"StandardPrices"的表,其中包含所有价格的名称(这样做的原因是我希望能够随时添加或删除价格)

 Plan Table:
 ID int primary key,
 plan Name varchar(200),
 ...
 PriceTable:
 ID int primary key,
 PlanId int foreign key references plan(ID)
 PriceName ID foreign key standardprices(id)
 StandardPrices:
 ID int primary key,
 PriceName varchar(200),
 DefaultPrice money

所以无论何时创建一个计划,它都会自动创建一个包含StandardPrice列表中所有价格的列表(带有默认值)。

我的问题是,我需要,每当我创建一个新的StandardPrice时,它会自动检查该价格是否存在于每个计划中,如果不存在,则在该计划的价格表中创建一个条目。

我使用存储过程,并认为最好的方法是通过SQL。

创建StandardPrices时:

   begin      
   insert into StandardPrices (PriceName, Defaultprice)
       values (@priceName, @DefaultPrice)
   end
   begin
   //list all plans.
   //cross reference PriceTable to see if plan exists
   //if not insert priceplan with default value
   end

我有点困惑,我怎么能实现这样一个sql命令?

在多个结果上不存在SQL插入

我觉得应该是这样的:

insert into PriceTable (PlanId, PriceName)
select PlanId, @priceName
from Plan
where not exists 
  (select null from PriceTable where PriceTable.PlanId = Plan.PlanId)

这样做:

if not exists
(
    select *
    from PriceTable
    where PriceName = @priceName
)
begin
    insert into PriceTable(PriceName)
    values(@priceName)
end

它的作用是有条件地检查PriceName是否已经在PriceTable中。如果它是而不是,那么它将把新的@priceName插入PriceTable。我不确定你原来的帖子PlanID的值是多少,但你应该从我上面的查询中得到这个想法。

您需要获得所有计划的列表,LEFT OUTER连接到适当的价格。如果价格记录为空,则没有适当的关联,因此添加它。

您可能需要使用游标来遍历结果并添加价格。

之类的. .

SELECT Plan.Id, Price.Id
FROM Plan LEFT OUTER JOIN Price ON Price.PlanId = Plan.Id
WHERE Price.Id = [Your New Price Id]

使用MERGE并假设您的ID列具有IDENTITY属性:

MERGE INTO PriceTable
   USING 
      (
        SELECT p1.ID AS PlanId, sp1.PriceName 
         FROM Plan p1 
            CROSS JOIN StandardPrices sp1
      ) AS SourceTable
   ON PriceTable.PlanId = SourceTable.PlanId 
      AND PriceTable.PriceName = SourceTable.PriceName 
   WHEN NOT MATCHED 
      THEN
   INSERT ( PlanId, PriceName )
            VALUES ( PlanId, PriceName ) ;

这里是一个更完整的草图,其中我将看似冗余的ID列降级,将name列提升为关系键,添加约束,在表之间使用一致的命名,将MONET更改为DECIMAL,等等:

CREATE TABLE Plans
(
  plan_name VARCHAR(200) NOT NULL
                         UNIQUE
                         CHECK ( plan_name <> ' ' )
) ;
CREATE TABLE StandardPrices
(
  price_name VARCHAR(200) NOT NULL
                          UNIQUE
                          CHECK ( price_name <> ' ' ),
  default_price DECIMAL(19, 4) NOT NULL
                               CHECK ( default_price >= 0 )
) ;
CREATE TABLE Prices
(
  plan_name VARCHAR(200) NOT NULL
                         REFERENCES Plans ( plan_name ),
  price_name VARCHAR(200) NOT NULL
                          REFERENCES StandardPrices ( price_name ),
  UNIQUE ( plan_name, price_name )
) ;
DECLARE @plan_name_new VARCHAR(200) ;
DECLARE @price_name_1 VARCHAR(200) ;
DECLARE @default_price_1 DECIMAL(19, 4) ;
DECLARE @price_name_2 VARCHAR(200) ;
DECLARE @default_price_2 DECIMAL(19, 4) ;
SET @plan_name_new = 'One'
SET @price_name_1 = 'Day'
SET @default_price_1 = 55 ;
SET @price_name_2 = 'When'
SET @default_price_2 = 99
INSERT INTO Plans ( plan_name )
   VALUES ( @plan_name_new ) ;
INSERT INTO StandardPrices ( price_name, default_price )
   VALUES ( @price_name_1, @default_price_1 ) ;
INSERT INTO StandardPrices ( price_name, default_price )
   VALUES ( @price_name_2, @default_price_2 ) ;
MERGE INTO Prices
   USING 
      (
        SELECT p1.plan_name, sp1.price_name
         FROM Plans p1 
            CROSS JOIN StandardPrices sp1
      ) AS SourceTable
   ON Prices.plan_name = SourceTable.plan_name
      AND Prices.price_name = SourceTable.price_name
   WHEN NOT MATCHED 
      THEN
   INSERT ( plan_name, price_name )
            VALUES ( plan_name, price_name ) ;

(MySql)我建议你创建一个临时表;它是干净和可读的(我将添加不带别名,以更可读):

CREATE TEMPORARY TABLE tempTable
(
    table1FK    varchar(250),
    table2Value varchar(250)
);
INSERT INTO tempTable(table1FK, table2Value)
VALUES ('it', '+39'),
       ('lt', '+370'),
       ('gb', '+44'),
       ('cn', '+86');
INSERT INTO table2(table1FK_id, table2Value)
SELECT table1.id, tempTable.prefix
FROM tempTable
         inner join table1 ON table1.code = tempTable.country_code
         left join table2 ON table2.country_id = table1.id
where table2.id is null;
DROP temporary TABLE tempTable;