SQL: использовать одну и ту же строку для INSERT и UPDATE? - PullRequest
3 голосов
/ 26 апреля 2009

Синтаксис INSERT, который я использовал, это

INSERT INTO TableName VALUES (...)

Используемый мной синтаксис ОБНОВЛЕНИЯ

UPDATE TableName SET ColumnName=Value WHERE ...

Итак, во всем моем коде мне нужно сгенерировать 2 строки, что приведет к чему-то вроде этого

insertStr = "(27, 'John Brown', 102)";
updateStr = "ID=27, Name='John Brown', ItemID=102";

и затем использовать их отдельно

"UPDATE TableName SET " + updateStr + " WHERE ID=27 " +
"IF @@ROWCOUNT=0 "+
"INSERT INTO TableName VALUES (" + insertStr + ")"

Меня начинает беспокоить, когда я работаю с таблицами с примерно 30 столбцами.

Разве мы не можем сгенерировать только одну строку для INSERT и UPDATE?

например. с использованием insertStr выше для оператора UPDATE или updateStr для оператора INSERT, или совершенно новым способом?

Ответы [ 7 ]

7 голосов
/ 26 апреля 2009

Я думаю, вам нужен совершенно новый подход. Вы открыты для SQL-инъекций . Предоставьте нам некоторый пример кода о том, как вы получаете свои входные данные и отправляете отчеты в базу данных. альтернативный текст http://goose.ycp.edu/~weddins/440/S09%20IFS440%20Bobby%20Drop%20Tables.PNG

6 голосов
/ 26 апреля 2009

Насколько я знаю, то, что вы описываете, невозможно в ANSI SQL или в любом его расширении, которое я знаю. Тем не менее, я в основном знаком с MySQL, и это, вероятно, полностью зависит от того, какую СУБД вы используете. Например, MySQL имеет синтаксис «INSERT ... ON DUPLICATE KEY UPDATE ...», который похож на то, что вы там опубликовали, и объединяет запрос INSERT с запросом UPDATE. Положительным моментом является то, что вы объединяете две возможные операции в один запрос, однако части запроса INSERT и UPDATE, по общему признанию, различаются.

Как правило, подобные вещи можно абстрагировать с помощью слоя ORM в вашем приложении. Что касается необработанного SQL, мне будет интересен любой синтаксис, который работает так, как вы описываете.

2 голосов
/ 26 апреля 2009

Некоторые СУБД имеют расширение для этого, но почему бы вам просто не предоставить функцию, которая сделает это за вас? Мы на самом деле сделали это раньше.

Я не уверен, какой язык вы используете, но у него, вероятно, есть ассоциативные массивы, где вы можете написать что-то вроде:

pk{"ID"}   = "27"
val{"Name"} = "'John Brown'"
val{"ItemID"} = "102"
upsert ("MyTable", pk, val)

и, если у него нет ассоциативных массивов, вы можете эмулировать их с несколькими целочисленными массивами строк.

В нашей функции upsert() мы просто сконструировали строку (update, затем insert, если update не удалось) и передали ее нашей СУБД. Мы держали первичные ключи отдельно от других наших полей, поскольку это значительно упростило построение оператора обновления (столбцы первичного ключа были добавлены в предложение where, другие столбцы были просто установлены).

Результатом вышеуказанных вызовов будет следующий SQL (у нас была другая проверка на сбой update, но я поместил ваш @@rowcount в этом примере):

update MyTable set
    Name = 'John Brown',
    ItemID = 102
    where ID = 27
if @@rowcount=0
    insert into MyTable (ID, Name, ItemID) values (
        27,
        'John Brown',
        102
    )

Это одно решение, которое хорошо сработало для нас. Без сомнения, есть и другие.

2 голосов
/ 26 апреля 2009

Ну, а как насчет заявлений? Возможно, вы захотите заглянуть в ORM, чтобы справиться с этим для вас ...

1 голос
/ 26 апреля 2009

SQL Server 2008:

MERGE dbo.MyTable AS T
USING
 (SELECT  
  @mykey AS MyKey
  @myval AS MyVal
  ) AS S

ON (T.MyKey = S.MyKey)

WHEN MATCHED THEN 
  UPDATE  SET 
    T.MyVal = S.MyVal
WHEN NOT MATCHED THEN
  INSERT (MyKey, MyVal)
  VALUES (S.MyKey, S.MyVal)

MySQL:

INSERT (MyKey, MyVal)
INTO MyTable
VALUES({$myKey}, {$myVal})
ON DUPLICATE KEY UPDATE myVal = {$myVal}
1 голос
/ 26 апреля 2009

Если подумать, INSERT и UPDATE - это одно и то же. Они сопоставляют имена полей со значениями, за исключением того, что ОБНОВЛЕНИЕ имеет фильтр. Создав ассоциативный массив, где ключ - это имя поля, а значение - это значение, которое вы хотите присвоить полю, вы получаете свое отображение. Вам просто нужно преобразовать его в правильный формат строки в зависимости от INSERT или UPDATE. Вам просто нужно создать функцию, которая будет обрабатывать преобразование на основе заданных параметров.

1 голос
/ 26 апреля 2009

Некоторые базы данных имеют проприетарные расширения, которые делают именно это.

Я согласен, что синтаксис INSERT и UPDATE может быть более согласованным, но сейчас это просто факт жизни - он не изменится сейчас. Для многих сценариев лучшим вариантом является «совершенно новый путь»: используйте библиотеку объектно-реляционного отображения (или даже слой слабого чая, такой как .NET DataSets), чтобы абстрагироваться от различий и перестать беспокоиться о низкоуровневом SQL синтаксис. Конечно, это нереальный вариант для каждого приложения, но он позволит вам просто создать или обновить объект, вызвать метод Save и заставить библиотеку определить синтаксис SQL для вас.

...