Ефикасен начин за актуализиране на SQL таблица за „отношения“.

Да кажем, че имам три правилно нормализирани таблици. Един за хора, един за квалификации и един за съпоставяне на хората с квалификации:

хора:

id | Name
----------
1  | Alice
2  | Bob

Степени:

id | Name
---------
1  | PhD
2  | MA

Хора до степени:

person_id | degree_id
---------------------
1         | 2         # Alice has an MA
2         | 1         # Bob has a PhD

Тогава трябва да актуализирам това картографиране чрез моя уеб интерфейс. (Направих грешка. Боб има бакалавърска, а не докторска степен, а Алис току-що получи бакалавърска степен по английски език.)

Има четири възможни състояния на тези съпоставяния на отношенията "един към много":

  • беше вярно преди, сега трябва да е невярно
  • беше невярно преди, сега трябва да е вярно
  • беше вярно преди, трябва да остане вярно
  • беше невярно преди, трябва да остане невярно

това, което не искам да правя, е да прочета стойностите от четири квадратчета за отметка, след което да натисна базата данни четири пъти, за да кажа „Боб имаше ли бакалавърска степен преди? Е, сега има.“ „Имал ли е Боб докторска степен преди? Защото вече няма“ и т.н.

Как другите хора се справят с този проблем?

Любопитен съм да видя дали някой друг ще стигне до същото решение като мен.

АКТУАЛИЗАЦИЯ 1: onedaywhen предлага същото нещо, което ми хрумна -- просто изтрийте всички стари записи, правилни или не, и ВМЪКНЕТЕ нови.

АКТУАЛИЗАЦИЯ 2: potatopeelings предлага добавяне на код към формуляра, който съхранява оригиналната стойност на полето, което може да се сравни с новата стойност при изпращане.


person AmbroseChapel    schedule 15.06.2010    source източник
comment
какви са контролите на вашия уеб интерфейс? Всички квадратчета за отметка за стойности в таблицата с хора и степени? Една актуализация за един народ ли е?   -  person IsmailS    schedule 15.06.2010
comment
Надявам се, че този отговор ще помогне stackoverflow.com/questions/2273815/   -  person IsmailS    schedule 15.06.2010
comment
Можете да приемете различни стратегии в зависимост от вашата конкретна база данни и версия   -  person josephj1989    schedule 15.06.2010
comment
Този отговор адресира проблема, но само за определен тип SQL сървър, освен ако не съм объркан.   -  person AmbroseChapel    schedule 15.06.2010
comment
MERGE е за SQL Server 2008. Но примерът BEGIN TRAN - COMMIT ще работи за предишни версии.   -  person potatopeelings    schedule 15.06.2010
comment
Да, Исмаил, това са квадратчета за отметка. И josephj, надявам се на общ коментар по въпроса, а не на нещо специфично за изпълнението. Обикновено използвам MySQL.   -  person AmbroseChapel    schedule 16.06.2010
comment
Сега го виждам. Но не мога да използвам MERGE в MySQL, така че все още търся обобщен отговор, благодаря.   -  person AmbroseChapel    schedule 16.06.2010
comment
В такъв случай бихте могли да маркирате въпроса си с MySQL. Ще го направя.   -  person IsmailS    schedule 16.06.2010


Отговори (2)


Логично, UPDATE е DELETE, последвано от INSERT (помислете, че тригерите на SQL Server могат да имат достъп до логически таблици с имена inserted и deleted, но няма updated таблица). Така че трябва да можете да уцелите базата данни само два пъти, т.е. първо DELETE всички редове (правилни или не) за Боб, второ INSERT всички правилни редове за Боб.

Ако искате да достигнете до базата данни само веднъж, обмислете използването на стандартен SQL MERGE, ако приемете, че вашата СУБД го поддържа (SQL Server го въведе през 2008 г.).

person onedaywhen    schedule 15.06.2010
comment
Аха! Това първо DELETE, след това INSERT ми се стори като най-елегантния начин за заобикаляне на сложността. Някой иска ли да коментира? onedaywhen отговорът няма нито гласове за, нито против... - person AmbroseChapel; 16.06.2010

Ако приемем, че потребителският интерфейс е решетка с квадратчета за отметка (1. в коментар на Ismail във въпроса)

           MA      PhD    
Alice      x 
Bob                 x

където x представлява отметнати квадратчета. Бих използвал предния скрипт, за да изпратя само промените обратно на сървъра. След това правете INSERT и DELETE в People-to-degrees под една транзакция или MERGE (както е посочено във връзката на Ismail)

BEGIN TRAN
INSERT query
DELETE query
COMMIT

Ще подадете на заявката INSERT (и DELETE) списък с ID на хора, двойки ID на степени като. За вашия пример заявката INSERT ще бъде единичната двойка (2,2), а за заявката DELETE единичната двойка (2,1).

person potatopeelings    schedule 15.06.2010
comment
Как предният скрипт ще изпрати само промените? Искате да кажете, че за всяко квадратче за отметка ще има съответен ‹input type=hidden› с оригиналната стойност? - person AmbroseChapel; 16.06.2010
comment
Това е един от начините да го направите. Други начини са 1. Добавете допълнителен атрибут към квадратчето за отметка със старата стойност, до която по-късно можете да получите достъп с .getAttribute 2. Добавете събитие onclick към всяко квадратче за отметка, което следи промените 3. Създайте низ / масив от мрежата стойности при зареждане на страницата и onsubmit сравнява изпратените стойности с това (низ, изграден при зареждане). - person potatopeelings; 16.06.2010
comment
Аз съм старата школа. Не мислех да разчитам на скриптов език от страна на клиента! - person AmbroseChapel; 16.06.2010