2012-11-20 12 views
7

Mam tabelę, która zawiera identyfikator sklepu i identyfikator gracza oraz punkty gracza. Co chcę zrobić, to przenieść punkty ze sklepu do drugiego, chodzi o to, że identyfikator sklepu i identyfikator gracza tworzą unikalny indeks. Co chcę zrobić, to duplikować aktualizację klucza, zamiast pozwolić mu zawieść, dodawać punkty jednego wpisu do drugiego i usuwać wpis "od". Coś jak:aktualizacja duplikatu aktualizacji klucza

UPDATE `playerspoints` 
SET `boardId`=$to 
WHERE `boardId`=$from 
ON DUPLICATE KEY UPDATE `points`=.... get the idea? 
+0

Zgaduję, że byłoby to prostsze z 2 (ish) zapytaniami i blokiem if/else. Czy jest jakiś szczególny powód, dla którego chcesz to zrobić w ten sposób? – landons

+2

Jak najlepiej wykorzystać potencjał języka, to dobra praktyka. Chodzi raczej o odkrywanie rzeczy i szybsze ich wykonywanie. –

+0

Naprawdę mam nadzieję, że to [poprawne wychodzenie SQL] (http://bobby-tables.com/), jeśli jest wdrożone do produkcji. Widzenie nagich zmiennych jest niepokojące. – tadman

Odpowiedz

3

Można jedynie dokonać zmian w kontekście jednego sprzecznych rzędu w obszarze ON DUPLICATE KEY. Ponadto, o ile mi wiadomo, jest to właściwość oświadczenia INSERT.

Potrzebna jest prosta księga, w której zapisuje się dodatki i odjęcia z wagi, a następnie tabuluje je ręcznie lub za pomocą wyzwalaczy.

Na przykład, najprostszym rozwiązaniem jest:

INSERT INTO points_adjustments (boardId_from, boardId_to, points) 
    VALUES (?, ?, ?) 

To może być łatwiej reprezentowane parę wpisów:

INSERT INTO points_adjustments (boardId, points) 
    VALUES (?, ?) 

Można by dodać jeden wpis do + n punktów, a pasujący do -n. W każdej chwili możesz uzyskać równowagę za pomocą SUM(points). Możesz zawinąć to w VIEW, aby ułatwić pobieranie lub, jeśli chcesz, zdenormalizować sumy w kolumnie innej tabeli za pomocą wyzwalacza.

Prosty spust wyda następujące oświadczenie dla każdego dotkniętego boardId:

INSERT INTO balances (boardId, points) VALUES (?, ?) 
    ON DUPLICATE KEY SET points=points+VALUES(points) 

to uniknąć kolizji kluczowe w pierwszej kolejności i zapewnia skontrolowania rejestr transakcji, które miały miejsce.

W każdym przypadku, aby zrobić to wszystko automatycznie, prawdopodobnie będziesz musiał użyć spustu.

+0

Podoba mi się to rozwiązanie, ale nigdy nie korzystałem z wyzwalaczy, chyba że nadszedł dla mnie czas. Co do ucieczki ... $ od \t = (int) mysql_real_escape_string ($ _ REQUEST ['from'])); \t \t \t \t $ to \t = (int) mysql_real_escape_string ($ _ REQUEST ['to'])); \t \t \t \t $ delete = $ condition [mysql_real_escape_string ($ _ REQUEST ['delete'])]]; \t \t \t \t $ contest = $ condition [mysql_real_escape_string ($ _ REQUEST ['contest'])]]; czy mogę coś jeszcze zrobić? –

+0

Tak. Wyzwalacze będą logicznym kolejnym krokiem. Automatyczne usuwanie naruszeń ograniczeń było ambitną myślą :) – landons

+0

Tak ... użyj PDO (lub innej biblioteki abstrakcji DB). – landons

0

Nie. Nie można usunąć rekordu po naruszeniu ograniczeń w MySQL. Możliwe, że uruchamiasz przed wyzwalaczem aktualizacji, który sprawdza, czy nie doszło do naruszenia ograniczeń, ale nawet wtedy (od wersji 5.1) nie można modyfikować danych tego samego stołu (co i tak prawdopodobnie spowodowałoby niekończącą się pętlę w tym przypadku).

Tylko w połowie skończył przed odpowiedzią Tadmana. Podoba mi się jego pomysł, osobiście.

Powiązane problemy