Beiträge von Pille

    Wenn ich zwei Tabellen habe die zusammenhängen, dann kann ich doch auch beide löschen, oder?


    Beispiel:
    Tabelle1:

    Code
    Name	ID	Variable
    ------+------+------------
    Max   |   5  |	100
    Theo  |   45 |	222
    Tim   |   2  |	6


    Tabelle2:

    Code
    num	Variable1	Variable2
    ------+---------------+------------
    5     |   55          |	   100
    45    |   12          |	   262
    45    |   13          |	   212
    45    |   14          |	   252
    45    |   15          |	   222
    2     |   2           |	   6


    Wie muss der korrekte Syntax aussehen um alles mit ID 45 zu löschen?


    SQL
    DELETE Tabelle1,Tabelle2 FROM Tabelle1,Tabelle2 WHERE Tabelle1.ID=45 AND Tabelle2.num=45


    So? Wenn ja, verstehe ich nicht, warum ich 2x die Tabellen auflisten lassen muss.

    Zu dem Timer:
    Ich habe einen vor dem CALL-Query und nach dem CALL-Query gesetzt, keine Wirkung.
    Alle SELECT-Querys funktionieren nach dem CALL-Query nicht mehr.


    Zu Zweitens:
    Ich habe das ganze in HeidiSQL ausprobiert, es funktioniert einwandfrei.
    Außerdem funktioniert das Werte auslesen dieses CALL-Querys auch, es kommt ja die richtige Zahl raus.


    Ich fürchte es könnte wirklich ein Bug im Plugin sein.
    Wer entwickelt das denn? Wem könnte ich diesen Fehler mitteilen?

    Oha, da ist aber die Kacke am dampfen:


    Der Problemverursacher waren folgende Zeilen im Filterscript:
    mysql_function_query(cH,"CALL TestProz(25);","OnTest","");


    //woanders
    forward OnTest();
    public OnTest()
    {
    new rows=cache_get_row_count();
    new name[25];
    cache_get_row(0,0,name);
    printf("Name: %s",name);
    return 1;
    }


    Der Serverlog sieht wiefolgt aus:

    Code
    [22:28:14] Name: TestEvent2 // Das ist die Debugnachricht bei OnTest!
    [22:28:14] ---------------- MYSQL ERROR ------------------ // Alle SELECT-Querys dannach, egal ob Filterscript oder Gamemode, können nicht ausgeführt werden.
    [22:28:14] Error #2014 im MySQL-Syntax:
    [22:28:14] Commands out of sync; you can't run this command now
    [22:28:14] Callback: 'EM_OnLoadFS'
    [22:28:14] Query: 'SELECT Name FROM EM_E'


    DerMySQL-Log:

    Code
    [22:28:14] [DEBUG] mysql_tquery - connection: 1, query: "CALL TestProz(25);", callback: "OnTest", format: "(null)"
    [22:28:14] [DEBUG] mysql_tquery - connection: 1, query: "SELECT Name FROM EM_E", callback: "EM_OnLoadFS", format: "(null)"
    [22:28:14] [DEBUG] CMySQLQuery::Execute[OnTest] - starting query execution
    [22:28:14] [DEBUG] CMySQLQuery::Execute[OnTest] - query was successfully executed within 0.271 milliseconds
    [22:28:14] [DEBUG] CMySQLResult::CMySQLResult() - constructor called
    [22:28:14] [DEBUG] CMySQLQuery::Execute[EM_OnLoadFS] - starting query execution
    [22:28:14] [ERROR] CMySQLQuery::Execute[EM_OnLoadFS] - (error #2014) Commands out of sync; you can't run this command now
    [22:28:14] [DEBUG] CMySQLQuery::Execute[EM_OnLoadFS] - error will be triggered in OnQueryError


    So sieht meine Prozedor aus (die man mit MySQL erstellt und mit CALL aufruft:

    SQL
    CREATE DEFINER=`root`@`localhost` PROCEDURE `TestProz`(IN `eID` SMALLINT(4))
    	LANGUAGE SQL
    	NOT DETERMINISTIC
    	CONTAINS SQL
    	SQL SECURITY DEFINER
    	COMMENT ''
    SELECT Name FROM EM_E WHERE ID=eID


    Wenn ich den Query mit dem CALL auskommentiere, funktionieren alle SELECT-Querys.
    Ist das ein Fehler im Plugin oder verwende ich die PROCEDURE-Funktion falsch?


    Hier nochmal ein ausführlicher Test:

    Spoiler anzeigen
    Folgendes Script wurde als Gamemode geladen (ohne jegliche Filterscripts!)
    #include <a_samp>
    #include <a_mysql>

    Spoiler anzeigen
    main(){}

    Spoiler anzeigen
    public OnGameModeInit()
    {
    cH=mysql_connect("127.0.0.1","root","samp","1234");
    if(!cH)
    {
    printf("Verbindung fehlgeschlagen!");
    SendRconCommand("exit");
    }
    mysql_log(LOG_ALL);
    mysql_function_query(cH,"CALL TestProz(10);","OnCall","");
    return 1;
    }

    Spoiler anzeigen
    forward OnCall();
    public OnCall()
    {
    printf("Da sind wir.");
    printf("Endergebnis: Spieler-ID 10 hat Level %i. ",cache_get_row_int(0,0));
    mysql_function_query(cH,"SELECT 1","OnCall2","");
    print("Query!");
    return 1;
    }

    Spoiler anzeigen
    forward OnCall2();
    public OnCall2()
    {
    printf("Nummer %i",cache_get_row_int(0,0));
    return 1;
    }

    Spoiler anzeigen
    public OnQueryError(errorid, error[], callback[], query[], connectionHandle)
    {
    print("---------------- MYSQL ERROR ------------------");
    printf("Error #%02d im MySQL-Syntax:",errorid);
    printf(error);
    printf("Callback: '%s'",callback);
    printf("Query: '%s'",query);
    print("-----------------------------------------------");
    return 1;
    }

    Spoiler anzeigen
    Server-Log:

    Code
    ----------Loaded log file: "server_log.txt".----------SA-MP Dedicated Server----------------------v0.3z-R2, (C)2005-2014 SA-MP Team[22:58:57] filterscripts = ""  (string)[22:58:57] [22:58:57] Server Plugins[22:58:57] --------------[22:58:57]  Loading plugin: mysql[22:58:57]  >> plugin.mysql: R39-2 successfully loaded.[22:58:57]   Loaded.[22:58:57]  Loading plugin: crashdetect[22:58:57]   CrashDetect v4.10 is OK.[22:58:57]   Loaded.[22:58:57]  Loaded 2 plugins.[22:58:57] [22:58:57] Ban list[22:58:57] --------[22:58:57]  Loaded: samp.ban[22:58:57] [22:58:57] [22:58:57] Filterscripts[22:58:57] ---------------[22:58:57]   Loaded 0 filterscripts.[22:58:57] Number of vehicle models: 0[22:58:57] Da sind wir.[22:58:57] Endergebnis: Spieler-ID 10 hat Level 22. [22:58:57] Query![22:58:57] ---------------- MYSQL ERROR ------------------[22:58:57] Error #2014 im MySQL-Syntax:[22:58:57] Commands out of sync; you can't run this command now[22:58:57] Callback: 'OnCall2'[22:58:57] Query: 'SELECT 1'[22:58:57] -----------------------------------------------

    Spoiler anzeigen
    MySQL-Log:

    Code
    [22:58:57] [DEBUG] mysql_tquery - connection: 1, query: "CALL TestProz(10);", callback: "OnCall", format: "(null)"[22:58:57] [DEBUG] CMySQLConnection::Connect - establishing connection to database...[22:58:57] [DEBUG] CMySQLConnection::Connect - establishing connection to database...[22:58:57] [DEBUG] CMySQLConnection::Connect - connection was successful[22:58:57] [DEBUG] CMySQLConnection::Connect - connection was successful[22:58:57] [DEBUG] CMySQLConnection::Connect - auto-reconnect has been enabled[22:58:57] [DEBUG] CMySQLConnection::Connect - auto-reconnect has been enabled[22:58:57] [DEBUG] CMySQLQuery::Execute[OnCall] - starting query execution[22:58:57] [DEBUG] CMySQLQuery::Execute[OnCall] - query was successfully executed within 0.241 milliseconds[22:58:57] [DEBUG] CMySQLResult::CMySQLResult() - constructor called[22:58:57] [DEBUG] Calling callback "OnCall"..[22:58:57] [DEBUG] cache_get_row_int - row: 0, field_idx: 0, connection: 1[22:58:57] [DEBUG] CMySQLResult::GetRowData - row: '0', field: '0', data: "22"[22:58:57] [DEBUG] mysql_tquery - connection: 1, query: "SELECT 1", callback: "OnCall2", format: "(null)"[22:58:57] [DEBUG] CMySQLResult::~CMySQLResult() - deconstructor called[22:58:57] [DEBUG] CMySQLQuery::Execute[OnCall2] - starting query execution[22:58:57] [ERROR] CMySQLQuery::Execute[OnCall2] - (error #2014) Commands out of sync; you can't run this command now[22:58:57] [DEBUG] CMySQLQuery::Execute[OnCall2] - error will be triggered in OnQueryError[22:58:57] [DEBUG] Calling callback "OnQueryError"..

    Spoiler anzeigen
    Create-Code der Procedure:

    SQL
    CREATE DEFINER=`root`@`localhost` PROCEDURE `TestProz`(IN `Num` SMALLINT(4))	LANGUAGE SQL	NOT DETERMINISTIC	CONTAINS SQL	SQL SECURITY DEFINER	COMMENT ''SELECT Level FROM Accounts WHERE Nummer=Num


    Was mir sehr komisch vorkommt ist, dass zuerst der CALL-Query ausgesand wird, und dann die Verbindung aufgebaut wird zum MySQL-Server.
    Oder wurde sie vielleicht aufgebaut, aber nicht geloggt? Und dann wurde sie wieder verloren?
    Jeffry: ^^

    Ich habe die Fehlerquelle gefunden:
    Als ich das Filterscript, was sich ebenfalls seit neustem mit dem MySQL Server verbindet,
    nicht geladen habe, hat alles wunderbar funktioniert.


    Jetzt deshalb die Frage:
    Muss ich ein Filterscript mit dem MySQL-Server verbinden, wenn der Gamemode bereits eine Verbindung hat?
    Oder muss ich vlt. Reconnecten?
    Und wenn nein, wie bekomme ich die connectionHandle raus?


    Jeffry: :D

    Eigentlich nicht, weil ich ja kein mysql_free_result, mysql_store_result etc benutze,
    da das jetzt ja alles cache-basiert funktioniert.

    #define mysql_function_query mysql_tquery


    mysql_function_query(cH,"SELECT Name,AdminLevel FROM Accounts WHERE AdminLevel>0","mysql_Admins","");


    Hilft dir das was?

    Hallo,


    soeben habe ich mein MySQL-Plugin geupdated (+Includes etc.) auf Version R39-2.
    Ich benutze das Plugin von BlueG (https://github.com/pBlueG/SA-MP-MySQL/releases).


    Das einzige Problem, was ich habe ist, dass ich keinen SELECT-Query mehr absenden kann.


    Code
    (error #2014) Commands out of sync; you can't run this command now


    Hier einige Ausschnitte vom Log:


    Warum passiert das?

    SQL
    INSERT INTO Tabellenname (Name) VALUES ('TestNAME') ON DUPLICATE KEY UPDATE Name='TestNAME'


    Ich hatte es bis gerade eben so, aber dann ist mir die Lösung gekommen :D


    SQL
    INSERT INTO Tabellenname (Name) VALUES ('TESTNAme') ON DUPLICATE KEY UPDATE Name=Name


    Und so funktioniert es perfekt, herzlichen Dank! :)

    Herzlichen Dank, Jeffry, und wieder rettest du meine Existenz :D


    Klappt super :thumbup:


    //edit:
    Doch nicht... Wenn dann versucht wird ein Datensatz, den es schonmal gibt, einzufügen, wird er ja aktualisiert.
    Leider wird die Groß- und Kleinschreibung mitgeändert, sodass ungewollt Daten in der Datenbank verändert werden.
    Jeffry:

    Ich möchte einen neuen Eintrag in eine Tabelle einfügen, aber die Spalte "Name" muss einzigartig sein.
    Deshalb muss ich erst überprüfen, ob bereits eine Zeile existiert, wo in der Spalte "Name" derselbe Wert drinsteht wie den, den der Spieler gerade einfügen will.
    -> Select-Abfrage, neuer Callback, dort INSERT-Query, neuer Callback, INSERT_ID speichern.


    Das ist aber sehr umständlich, deswegen habe ich mir überlegt, ob das vielleicht einfacher geht.
    Ich habe in der Spalte "Name" einen Index gesetzt (Unique), sodass es nicht möglich ist zwei gleiche Werte einzufügen.


    Problem ist nur, dass jetzt bei identischen Daten, MySQL einen Fehler meldet - und nicht den Callback aufruft und mir sagt,
    dass unglücklicherweise keiner von den Querys erfollgreich in die Datenbank eingefügt werden konnte (mysq_affect_rows).
    Nur der Callback OnQueryError wird aufgerufen.



    Muss ich das mit zwei Callbacks und zwei Querys machen oder geht das auch einfacher? (z.B. siehe Beispiel oben)

    Hallo,


    kann man mit MySQL eine If-Abfrage gesalten, die einen Datensatz einfügt, wenn ein bestimmtes Ereignis eintritt?


    Warum ich es brauche?


    Umständlich:
    mysql_format(connection,string,"SELECT 1 FROM Tabellenname WHERE Name='%e' LIMIT 1;",inputtext);
    mysql_function_query(connection,string,true,"Check","is",playerid,inputtext);

    Umständlich:
    // Irgendwo anders...
    forward Check(playerid,inputtext[]);
    public Check(playerid,inputtext[])
    {
    new rows,fields;
    cache_get_data(rows,fields);
    if(rows!=0) return SendClientMessage(playerid,COLOR_GRAD1,"Dieser Name existiert bereits.");
    new string[128];
    mysql_format(connection,string,"INSERT INTO Tabellenname (Name) VALUES ('%e');",inputtext);
    mysql_function_query(connection,string,false,"Insert","i",playerid);
    }

    Umständlich:
    forward Insert(playerid);
    public Insert(playerid)
    {
    new string[128];
    format(string,sizeof(string),"Eintrag hinzugefügt (ID %i)",mysql_insert_id()); // Primary Key in Kombination mit AUTO_INCREMENT gesetzt.
    SendClientMessage(playerid,-1,string);
    }

    Einfach:
    mysql_format(connection,string,"INSERT INTO Tabellenname (Name) VALUES ('%e');",inputtext);
    mysql_function_query(connection,string,false,"Insert","i",playerid);

    Einfach:
    // Irgendwo anders...
    forward Insert(playerid);
    public Insert(playerid)
    {
    if(mysql_affected_rows()==0) // Datensatz konnte nicht eingefügt werden, da keine doppelten Einträge möglich sind
    {
    SendClientMessage(playerid,COLOR_GRAD1,"Dieser Name existiert bereits.");
    return 1;
    }
    new string[128];
    format(string,sizeof(string),"Eintrag hinzugefügt (ID %i)",mysql_insert_id()); // Primary Key in Kombination mit AUTO_INCREMENT gesetzt.
    SendClientMessage(playerid,-1,string);
    return 1;
    }



    Ich habe versucht das mit dem Unique-Index zu realisieren, leider wird bei einem doppelten Datensatz der Callback garnicht aufgerufen,
    sondern er wird weiter geleitet zu OnQueryError...


    Gibts eine andere Möglichkeit?



    Pille

    Probier mal das hier:



    tock FactionColor(playerid){
    switch(PlayerInfo[playerid][pLeader])
    {
    case 0: return 0xFFFFFFFF;
    case 1: return 0x00FF0AFF; // LSPD = Blau
    case 2: return 0x00AA00FF; // GS = Grün
    case 3: return 0xFF8800FF; // News = Orange
    }
    return 1;
    }

    Version 2.0


    Veränderungen:

    • Spieler-Textdraws statt globalen Textdraws
    • Ein globaler Timer statt einen für jeden Spieler
    • Weniger globale und lokale Variablennutzung
    • Performance-Verbesserungen
    • Zurücksetzen der globalen Variablen beim Verlassen des Servers


    Grob gesagt habe ich das Script, welches ich vor ungefähr zwei Jahren erstellt habe,
    an meinen heutigen Wissensstand angepasst.


    Den Link findet ihr beim ersten Beitrag.


    Verbesserungsvorschläge sind willkommen!