Отдельные sprocs для вставки / обновления или один Set sproc? - PullRequest
2 голосов
/ 07 октября 2009

Итак, я натолкнулся на случай, когда хранимая процедура, которая обрабатывает обновления для определенной таблицы, ничего не делает, потому что запись не существует [дух].

Итак, я решил изменить хранимую процедуру на:

 UPDATE    Table
 SET       col1 = @var1
 WHERE     Type = @type AND UserId = @userId 
 IF @@ROWCOUNT = 0
 BEGIN
  INSERT INTO Table
---etc....
 END

Таким образом, это, очевидно, решило проблему, и я переименовал sproc из UpdateTable в SetTable.

Это хорошая идея, или я должен что-то сделать на уровне приложения, где, если обновление возвращает 0 затронутых строк, вызвать процедуру вставки.

Ответы [ 5 ]

3 голосов
/ 07 октября 2009

Я предпочитаю «упор», который вы показали, потому что он позволяет мне держаться подальше от логики, связанной с постоянством. В приложении я просто хочу работать с моими объектами и «если я должен» попросить их сохранить / сохранить. При обновлении и вставке отдельно вы вынуждены думать об этом в модели предметной области. Но самое большое преимущество невежественности в том, что вы можете сосредоточиться на реальных проблемах бизнеса, а не на проблемах инфраструктуры.

Этот дизайн также помог мне перейти на ORM ранее в этом году, потому что у меня не было тонны вызовов «обновить» / «вставить», а вместо этого было просто «сохранить»

2 голосов
/ 07 октября 2009

Хорошо, если это соответствует ожиданиям приложения.

Если бизнес-намерение состояло только в том, чтобы обновить существующую запись ИЛИ, если приложение ожидало, что строка уже существует, и сохраненный процесс скрытно скрывает тот факт, что это не так, это может нарушить другую логику. Что если другая функция / процесс удалила строку по причине? Что если столбцы, которые не обновляются в строке, содержат информацию? Возможно, вставка изменит значения этих столбцов неожиданно.

Не говорю, что это так. Только такой человек, как вы, знакомый с приложением, может сказать, можно ли внести это изменение.

2 голосов
/ 07 октября 2009

Мне нравится иметь один для каждого. Я заставляю sproc выполнять определенную задачу вместо двух, что упрощает обслуживание и расширение.

1 голос
/ 08 октября 2009

Мне нравится ваш upsert (хотя и не хранимые процедуры :)) Но да, почему логика для метода, который не имеет ничего общего с выяснением того, нужно ли его обновлять или вставлять - просто позволяет sproc разобраться с этим.

1 голос
/ 07 октября 2009

Зависит.

В некоторых местах приложения будет иметь смысл сделать upsert, потому что вы не можете знать или не заботиться, должно ли текущее сохраненное состояние уже содержать запись. Тем не менее, в других местах вы хотите знать точно, и наличие записи о вставке или отсутствующей записи для обновления должно быть ошибкой.

В любом случае, когда вы решаете сделать «упор», вы должны быть осторожны, хотя из-за врожденных условий гонки. Два отдельных соединения могут пытаться обновить, оба видят @@ ROWCOUNT в 0, а затем оба пытаются вставить, что приводит к нарушению первичного ключа (если вам повезет) или хуже в несовместимом состоянии базы данных (дублирующаяся запись с разной информацией). Правильно подобрать такие операции довольно сложно. Вы должны либо убедиться, что UPDATE блокирует состояние (т. Е. Никакая другая транзакция не может быть вставлена), либо быть подготовленным к тому, чтобы ударить нарушение PK при вставке и обработать его соответствующим образом. Я предпочитаю более поздний вариант, поскольку окно условий гонки обычно довольно мало, и обработка исключения проще, чем предотвращение одновременной вставки.

Один из вариантов, который следует рассмотреть, - это использование нового оператора SQL Server 2008 MERGE , он предназначен для обработки таких случаев (и, наконец, догоняет SQL Server у других поставщиков, и Oracle, и MySQL предлагают эту функциональность для лет ...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...