"ON DUPLICATE" -> zmodyfikuj zduplikowany klucz, zapisz, jako NOWY rekord

0

Jak poucza instrukcja, w przypadku wystąpienia zduplikowanej wartości w kolumnie typu UNIQUE oba poniższe polecenia robią to samo:

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;
UPDATE t1 SET c=c+1 WHERE a=1;

Czyli nie umieszczają nowego rekordu, tylko aktualizują zawartość istniejącego i stanie się tak nawet wtedy, gdy zażyczę sobie zmodyfikowania jego indeksu.


Pytanie: czy w SQL da się napisać polecenie, które:

  • spróbuje wstawić nowy rekord,
  • w razie wykrycia duplikatu w kolumnie typu UNIQUE zmodyfikuje wpisywaną wartość, np wedle wzorca kn = kn +1,
  • i wstawi nowy rekord z tak poprawioną wartością / wartościami.

Czy da się to w ogóle zrobić w SQL i czy taka jest praktyka?

Czy może trzeba z poziomu PHP odczytać błąd i dopiero w oparciu i jego treść podejmować dalsze działania.
Ew. najpierw osobnym poleceniem sprawdzić, czy rekord z polem o takiej wartości już istnieje, a dopiero później wczytywać.

1

oba poniższe polecenia robią to samo

nie nie robia tego samego. Piewsze tworzy obiekt, chyba ze jest juz stworzony to wtedy wykonuje polecenie ON DUPLICATE KEY UPDATE c=c+1;

w razie wykrycia duplikatu w kolumnie typu UNIQUE zmodyfikuje wpisywaną wartość, np wedle wzorca kn = kn +1,

watpie zeby byl jakikolwiek mechanizm w czystym SQL by to Ci pozwolilo zrobic. Jeszcze jak masz procuderalne SQL to mozesz wywolywac procedure, ale logike w procedurach nie polecam

ja bym zrobil to co napisalas na samym koncu czyli najpierw sprawdzic czy taki rekord istnieje, jezeli tak to modifykowac parametry by unique nie byl naruszony i wtedy insertowac

pytanie, czemu masz sytuacje gdzie Unique Key moze sie powtarzac? Mozesz opisac sytuacje?

0
fasadin napisał(a):

ja bym zrobil to co napisalas na samym koncu czyli najpierw sprawdzic czy taki rekord istnieje, jezeli tak to modifykowac parametry by unique nie byl naruszony i wtedy insertowac

Dzięki :) Tak właśnie robię, ale poczytałam o tym ON DUPLICATE, i pomyślałam, że może głupia jestem i to trzeba jakąś inną magią w samym SQL załatwiać, bo się np. zawartość bazy może zmienić pomiędzy sprawdzeniem czy istnieje już taka wartość, a wpisaniem nowej wartości. I może coś takiego by np. zabezpieczało przed podobną sytuacją.

pytanie, czemu masz sytuacje gdzie Unique Key moze sie powtarzac? Mozesz opisac sytuacje?

Np. użytkownik wprowadza ręcznie dane towarów mających nazwy/identyfikatory. Ew. wczytuje je masowo z zewnętrznego pliku.
Nazwa / identyfikator powinna być unikalna, bo jest takim "pomocniczym ID dla ludzi".

No i jeśli w bazie jest już jeden reksio, to chcę, żeby kolejne był opisany jako - reksio -1, - reksio -2, żeby uzer widział, że wprowadził zdublowane nazwy i mógł je sobie później ręcznie przerobić np. na reksio duży i reksio mały.

2

Wiele się da napisać "naokoło" w SQLu, tylko zawsze trzeba sobie zadać pytanie, czy warto.
Jeśli dobrze zrozumiałem, to Twój problem dałoby się rozwiązać w jednym zapytaniu jakoś tak (nie wiem, jaki silnik, więc posłużę się para-T/SQL):

INSERT INTO tabela(...)
SELECT top 1 * FROM
(
   SELECT [tu podajesz takie dane, jakie mają zostać wstawione, jeśli w bazie istnieje już rekord] 
   FROM tabela 
   WHERE [tu wyszukujesz sobie rekord, który mógłby zostać zduplikowany - jeśli duplikatu nie ma, to zapytanie powinno nie zwracać niczego]

   UNION ALL

   SELECT [tu podajesz dane, które mają zostać wpisane, jeśli nie ma duplikatu]
)

Oczywiście trzeba wziąć pod uwagę np. to, że chcesz wstawić wspomnianego reksia, a w bazie już istnieje nawet reksio-9999.
O elegancji takiego rozwiązania się nie wypowiadam. Sam bym czegoś takiego do produkcji raczej nie wstawił, ale dla sportu - czemu nie :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1