Вставка SQL Server — операторы обновления

У меня есть следующий код: проблема в том, что когда я запускаю вставку, она будет вставляться в таблицу продуктов питания, даже если результат уже вставлен, как я могу написать оператор if, который будет проверять, существуют ли записи в NEWfoods уже в еде таблице, если они есть в еде, просто не делайте вставку, если их нет, то делайте вставку. Спасибо.

CREATE TABLE food (FoodName NVARCHAR(200), FoodType NVARCHAR(200));

CREATE TABLE NEWfoods (FoodName NVARCHAR(200), FoodType NVARCHAR(200));

-- populate base table (existing database table)
INSERT INTO food (FoodName, FoodType) VALUES 
 ('Apples', 'Fruit')
,('Avocado','Fruit')
,('Bananas', 'Fruit')
,('Mangos', 'Fruit')
,('Bread', 'Grain')
,('Cottage Cheese', 'Dairy')
,('Tacos', 'Meals')
,('Carrots', 'Vegetables')
,('Celery', 'Vegatables')

-- populate NEW table of foods which we will use ti import into;
INSERT INTO NEWfoods ( FoodName, FoodType ) VALUES  
 ('Avocado','Vegetables')
,('Apples','Fruit')
,('Salt','Preservative')
,('Turkey','Protein')
,('Bread','Grain')
,('Bread','Grain')
,('Tacos','Meals')


-- add in this list of foods if the pair does not exist;
-- this will become an INSERT INTO when said and done;

INSERT INTO food
SELECT
         f.FoodName
        ,f.FoodType 
    FROM food AS f
    WHERE NOT EXISTS (
        SELECT * FROM NEWfoods AS g
        where g.FoodName = f.FoodName
        AND g.FoodType = f.FoodType
        )

person user3345212    schedule 15.04.2014    source источник
comment
Я думаю, что здесь уже был дан ответ: stackoverflow.com/questions/16460397/   -  person Jason Lewis    schedule 15.04.2014
comment
возможный дубликат условной вставки MySQL   -  person Jason Lewis    schedule 15.04.2014


Ответы (4)


Я могу придумать несколько способов, если вы используете SQL Server 2008 или более позднюю версию:

Insert Food ( FoodName, FoodType )
Select FoodName, FoodType
From NewFood
Except
Select FoodName, FoodType
From Food

Другой - использовать оператор Merge:

Merge Food As target
Using NewFoods As source
    On source.FoodName = target.FoodName
            And source.FoodType = target.FoodType
When Not Matched Then
    Insert ( FoodName, FoodType )
    Values( source.FoodName, source.FoodType );
person Thomas    schedule 15.04.2014
comment
+1 - оба варианта четкие, лаконичные и элегантные. - person J0e3gan; 15.04.2014

Во-первых, вам нужно проверить какой-то идентификатор о наличии строки, то, что вы пытаетесь сделать, это «UPSERT», просто вам не нравится выполнять операцию обновления в случае, если строка существует уже.

Как обновить (обновить и вставить) в SQL Server 2005

вы можете просто пропустить часть «обновления» и продолжить; или вы также можете сделать название еды и тип еды первичным ключом, если строка уже присутствует для двустишие, она не позволит вам вставить другую строку и даст вам исключение; попробуйте любым способом.

person Brij Raj Singh - MSFT    schedule 15.04.2014
comment
Не путайте надо с в идеале. - person J0e3gan; 15.04.2014

Вы хотите сделать IF EXISTS, чтобы проверить, существует ли он уже. Если нет, то сделайте вставку. В противном случае, если новых записей не существует, он ничего не сделает, например:

    IF EXISTS(
    SELECT 1 FROM NEWfoods AS g 
    INNER JOIN food f ON g.FoodName = f.FoodName
      AND g.FoodType = f.FoodType)
   INSERT INTO food
   SELECT
     f.FoodName
    ,f.FoodType 
   FROM food AS f
   WHERE NOT EXISTS (
    SELECT * FROM NEWfoods AS g
    where g.FoodName = f.FoodName
    AND g.FoodType = f.FoodType
    )
person smoore4    schedule 15.04.2014

Один вариант — поместить оператор DELETE перед оператором INSERT INTO, например...

DELETE FROM food
WHERE FoodName IN (SELECT FoodName FROM NEWfoods)

... и упростите оператор INSERT INTO:

INSERT INTO food
SELECT -- Also, consider SELECT DISTINCT here unless you truly want repeat records like 'Bread'|'Grain', 'Bread'|'Grain'.
     nf.FoodName
    ,nf.FoodType 
FROM NEWfoods AS nf

В то время как результаты SELECT * FROM food...

FoodName                                           FoodType
-------------------------------------------------- --------------------------------------------------
Apples                                             Fruit
Avocado                                            Fruit
Bananas                                            Fruit
Mangos                                             Fruit
Bread                                              Grain
Cottage Cheese                                     Dairy
Tacos                                              Meals
Carrots                                            Vegetables
Celery                                             Vegatables

(9 row(s) affected)

...и SELECT * FROM NEWfoods это...

FoodName                                           FoodType
-------------------------------------------------- --------------------------------------------------
Avocado                                            Vegetables
Apples                                             Fruit
Salt                                               Preservative
Turkey                                             Protein
Bread                                              Grain
Bread                                              Grain
Tacos                                              Meals

(7 row(s) affected)

...до DELETE и пересмотренного INSERT INTO результат SELECT * FROM food становится следующим после выполнения операторов DELETE и пересмотренного INSERT INTO:

FoodName                                           FoodType
-------------------------------------------------- --------------------------------------------------
Avocado                                            Vegetables
Apples                                             Fruit
Bananas                                            Fruit
Mangos                                             Fruit
Salt                                               Preservative
Cottage Cheese                                     Dairy
Turkey                                             Protein
Carrots                                            Vegetables
Celery                                             Vegatables
Bread                                              Grain
Bread                                              Grain
Tacos                                              Meals

(12 row(s) affected)

Конечно, если множество NEWfoods записей будет полностью соответствовать food записям, это приведет к большому количеству ненужных удалений как есть. Вы можете улучшить оператор(ы) DELETEINSERT INTO), чтобы избежать этого, но это действительно зависит от особенностей данных (жизненного цикла).

Кроме того, вы могли бы, конечно, обернуть операторы DELETE и INSERT INTO в транзакцию, чтобы сделать их по принципу «все или ничего».

Как указывает @Thomas, EXCEPT и MERGE также являются отличными способами делать то, что вы хотите, если вы используете SQL Server 2008 или более позднюю версию; оба откровенно элегантнее; но отдельные операторы DELETE и INSERT INTO возможны.

person J0e3gan    schedule 15.04.2014