2012-04-06 13 views
1

Ich erstelle eine gespeicherte Prozedur, um Werte in vier Tabellen einzufügen. Der Punkt ist, SQL aus dem PHP herauszunehmen, um SQL-Injection zu verhindern und die Berechtigungen eines Benutzers besser zu definieren, dh anstatt unbegrenzten Zugriff auf INSERT, ALTER und DELETE Anweisungen zu haben, dürfen sie einfach nur die Prozedur ausführen Sie müssen die übergebenen Variablen einfügen.MySQL bedingte INSERT mit Parametern

Wenn jedoch ein Spieler bereits existiert, dann ist es unnötig, ihn wieder hinzuzufügen (und unmöglich, wenn ich es einzigartig gemacht habe). Das Problem tritt auf, weil zwischen der Spielertabelle und der Koordinatentabelle eine Eins-zu-Viele-Beziehung besteht.

Also, was ich möchte, ist eine bedingte INSERT zu testen, ob der Wert bereits existiert und wenn es tut, um mit der nächsten INSERT-Anweisung fortzufahren.

Hier ist die gespeicherte Prozedur:

CREATE PROCEDURE `acdb_extended`.`addAlliedMember` (IN accountNumber VARCHAR(255), 
    IN userName VARCHAR(255), IN serverInitial CHAR(1), IN galaxy TINYINT(2), 
    IN region TINYINT(2), IN system TINYINT(2), IN astro TINYINT(2), IN level TINYINT(2), 
    IN allianceName VARCHAR(255)) 
BEGIN 
    INSERT INTO player (account_number, username) 
    VALUES (accountNumber, userName); 

    INSERT INTO coordinates (player_ID, server_initial, galaxy, region, system, astro) 
    VALUES ((SELECT player_ID FROM player WHERE username = userName), serverInitial, 
     galaxy, region, system, astro); 

    INSERT INTO jumpgate (player_ID, coordinates_ID, level, usable) 
    VALUES ((SELECT player_ID FROM player WHERE username = userName), 
     (SELECT c.coordinates_ID FROM coordinates c WHERE c.server_initial = serverInitial 
      AND c.galaxy = galaxy AND c.region = region AND c.system = system AND c.astro = astro), 
     level, FALSE); 

    INSERT INTO relationship (player_ID, ally, alliance_name) 
    VALUES ((SELECT player_ID FROM player WHERE username = userName), 
     TRUE, allianceName); 
END 

Ich glaube, ich brauche ON DUPLICATE KEY aber ich kann seine Verwendung nicht ganz herausfinden.

Vielen Dank im Voraus für die Hilfe.

Antwort

1

Es gibt mehrere Möglichkeiten, dies mit MySQL zu tun. Eine einfache Lösung ist die Verwendung von INSERT IGNORE anstelle von INSERT. Ersteres macht im Grunde nichts, wenn die neue Zeile einen vorhandenen UNIQUE INDEX oder PRIMARY KEY Wert in der Tabelle dupliziert. Weitere Informationen finden Sie in der MySQL-Dokumentation unter INSERT Syntax. Sie können auch die Syntax INSERT INTO ... SELECT ... verwenden, die mehr Flexibilität bietet. Lassen Sie uns ein einfaches Beispiel geben. Die folgenden Aussagen zu tun im Grunde das Gleiche:

INSERT INTO foobar (foobar_id,display_name) VALUES (1,'one'); 

INSERT INTO foobar (foobar_id,display_name) 
    SELECT 1,'one' FROM dual; 

Wenn Sie die SELECT Abfrage ändern zu erkennen doppelte Einträge in foobar, können Sie das gewünschte Verhalten bekommen. Weitere Informationen finden Sie in der MySQL-Dokumentation unter INSERT ... SELECT Syntax.

Edit: Dies ist Werke in Stored Procedures und mit den Parametern der gespeicherten Prozedur:

CREATE PROCEDURE sp_foobar(IN _foobar_id int, IN _display_name varchar(255)) 
BEGIN 
    INSERT INTO foobar (foobar_id, display_name) 
     SELECT _foobar_id, _display_name 
     FROM dual; 
END; 
+0

Können Sie 'INSERT ... SELECT', wenn die Werte, die Sie einfügen möchten Parameter sind? Können Sie mir ein Beispiel dafür zeigen? – Arcadian

+0

Worauf bezieht sich dual? Ist es ein Tabellenname? Oder ist Dual ein Verweis auf Parameter? Ich verstehe die SELECT, aber ich verstehe nicht ganz genau, wo Sie das FROM zeigen. – Arcadian

+0

http://en.wikipedia.org/wiki/DUAL_table – nosid

0

Kannst du nicht tun es wie folgt vielleicht:

IF NOT EXISTS(SELECT NULL FROM player WHERE account_number=accountNumber AND username=userName) 
BEGIN 
    INSERT INTO player (account_number, username) 
    VALUES (accountNumber, userName); 

    INSERT INTO coordinates (player_ID, server_initial, galaxy, region, system, astro) 
    VALUES ((SELECT player_ID FROM player WHERE username = userName), serverInitial, 
     galaxy, region, system, astro); 
END