←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

Podbijanie ID w mysqlu przy insertowaniu d...

  • +
  • -
Robiin - zdjęcie Robiin 18.05.2024

    new Handle:insert_query = SQL_PrepareQuery(sql_connection,
        "INSERT INTO `missions` (`uid`, `name`, `desc`, `goal`) VALUES ('%s', '%s', '%s', '%i') \
        ON DUPLICATE KEY UPDATE `desc`='%s', `name`='%s', `goal`='%i';",
        uid, name, desc, goal, name, desc, goal);

Powyższe zapytanie robi jedną niefajną rzecz: mimo, że nie dodaje rekordu jeśli dana misja istnieje, to podbija id (to z AUTO_INCREMENT). Doczytałem, że to nie jest bug tylko celowe działanie, które ma coś tam zabezpieczyć. No ale nie widzi mi się robić osobnego zapytania (a w dodatku threaded), żeby sprawdzić czy dana misja jest już dodana.

Zapytanie ma na celu dodać rekord, jeśli taki nie istnieje, i zaktualizować go, jeśli coś się zmieniło.

Jakieś pomysły?

Odpowiedz

  • +
  • -
dasiek - zdjęcie dasiek 18.05.2024

1) zamknąć całą logikę ze sprwadzeniem czy misja istnieje czy nie w procedurze sql i ją wykonywać. 

2) przeprojektować bazę żeby nie korzystać z AUTO_INCREMENT.

Odpowiedz

  • +
  • -
Robiin - zdjęcie Robiin 18.05.2024

A może w sumie nonthreaded update? Przecież mogę robic update nawet jeśli rekord nie istnieje, wszystko przed zapytaniem z górnego postu? A potem tylko INSERT IGNORE

 

@edit No chyba, że by wciąż podbijało id...


Użytkownik Robiin edytował ten post 18.05.2024 22:25
Odpowiedz

  • +
  • -
Engi - zdjęcie Engi 19.05.2024

A dlaczego nie zrobisz tak:
 

INSERT INTO `missions` (`uid`, `name`, `desc`, `goal`) VALUES ('%s', '%s', '%s', '%i') \
        ON DUPLICATE KEY UPDATE `uid`=`uid`, `desc`='%s', `name`='%s', `goal`='%i'; 

btw: 

 

Nazwa 'desc' jest zastrzeżonym słowem kluczowym MySQL.

 

Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 19.05.2024

Jednej rzeczy nie rozumiem, co Ci to zmienia że auto_increment jest podbijane ?

Odpowiedz

  • +
  • -
Robiin - zdjęcie Robiin 19.05.2024

Technicznie rzecz biorąc to nic. Zanim zabraknie mi id, to minie dużo czasu. No ale wolałbym, żeby wszystko szło ładnie, a w dodatku czegoś się nauczę.

 

Na ten moment zrobiłem dwa zapytania. Pierwsze z update, drugie takie:

INSERT INTO `missions` (`uid`, `name`, `desc`, `goal`)
SELECT 'jakiesuid', 'jakasnazwa', 'jakisopis', 1
WHERE NOT EXISTS (
    SELECT 1
    FROM `missions`
    WHERE `uid` = 'jakiesuid'
);


btw: 

Cytat

 

Nazwa 'desc' jest zastrzeżonym słowem kluczowym MySQL.

 

https://stackoverflo...me-as-sql-types

 

 

You can use reserved keywords as identifiers as well, but you have to quote them.

 

Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 19.05.2024

BEGIN;


IF EXISTS (SELECT 1 FROM missions WHERE uid = '%s') THEN
    UPDATE missions SET `desc` = '%s', `name` = '%s', `goal` = '%i' WHERE uid = '%s';
ELSE
    INSERT INTO missions (`uid`, `name`, `desc`, `goal`) VALUES ('%s', '%s', '%s', '%i');
END IF;

COMMIT;

 

tylko nie wiem czy mysql w amxx to wspiera

 

Odpowiedz

  • +
  • -
Robiin - zdjęcie Robiin 20.05.2024

Nie wspiera, albo sam mysql ma problem z syntaxem ifów. Wymyśliłem coś takiego:

START TRANSACTION;

UPDATE `missions`
SET `name` = '%s', `desc` = '%s', `goal` = %i
WHERE `uid` = '%s';

SET @row_count = ROW_COUNT();

INSERT INTO `missions` (`uid`, `name`, `desc`, `goal`)
SELECT '%s', '%s', '%s', %i
WHERE NOT EXISTS (
    SELECT 1
    FROM `missions`
    WHERE `uid` = '%s'
    AND @row_count = 0
);

COMMIT;

Problem tylko w tym, że "Commands out of sync; you can't run this command now"


Użytkownik Robiin edytował ten post 20.05.2024 10:29
Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 20.05.2024

FROM w drugim select chyba brakuje

Odpowiedz

  • +
  • -
Robiin - zdjęcie Robiin 20.05.2024

Jest git, w drugim właśnie jest from. A pierwszy (ten z insert) to tylko wymienione wartości do wprowadzenia

Odpowiedz

  • +
  • -
dasiek - zdjęcie dasiek 21.05.2024

Sobie machnąłem taką tabele na testowym serwerze

CREATE TABLE `missions` (`uid` INT UNSIGNED NOT NULL AUTO_INCREMENT , `desc` VARCHAR(32) NOT NULL , `goal` INT(1) UNSIGNED NOT NULL , `name` VARCHAR(32) NOT NULL , PRIMARY KEY (`uid`))

 Dodałem do niego dwa rekordy
 

INSERT INTO `missions` (`uid`, `desc`, `goal`, `name`) VALUES (NULL, 'ASDF', '1', 'ASDF');
INSERT INTO `missions` (`uid`, `desc`, `goal`, `name`) VALUES (NULL, 'DUPA', '1', 'DUPA');

Sprawdziłem, jaki jest następny Następny Autoincrement 

SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'XYZ' AND TABLE_NAME = 'missions';

Zwróciło mnie "3" - więcj jest ok.

Następnie podpytałem trochę ejaja co tu się dzieje (skoro ma zabrać moją pracę, to musi się znać na robocie, a ze jest darmowy i ostatnio zrobił progress to czemu nie) i mi zasugerował albo ON DUPLICATE KEY, albo procedurę. Na pytanie jak zapobiec aktualizacji autoincrement powiedział tak

 

Jeśli chcesz uniknąć aktualizacji kolumny id oznaczonej jako AUTO_INCREMENT podczas użycia INSERT ... ON DUPLICATE KEY UPDATE, musisz upewnić się, że ta kolumna nie jest uwzględniona w sekcji UPDATE. W sekcji UPDATE powinny być tylko te kolumny, które chcesz zaktualizować.

 

I dał mi przykład. zmodyfikowałem go pod moje testowe tabele.

INSERT INTO missions (uid, `desc`, `goal`, `name`) VALUES (2, 'example', 1, 'value1') ON DUPLICATE KEY UPDATE `desc` = VALUES(`desc`), `name` = VALUES(`name`);

O dziwo, rekordy zostały zaktualizowane, a `SELECT AUTOINCREMENT` który juz wcześniej zrobiłem nadal zwrócił mi 3.

Więc dodałem następne dwa rekordy, mam pięknie ajdiki 1,2,3,4, więc coś mnie tu nie pasuje  :krecka_dostal:

 

Swoją drogą, postarał się nasz ejaj, bardzo dużo treści wygenerował, łapcie link: https://chatgpt.com/...a1-0cae3b147fca

 


dasiek (21.05.2024 09:25):

A moze to być kwestia tego, że na testówce mam MariaDB:10.3.22, a nie mysql...

Odpowiedz

  • +
  • -
Engi - zdjęcie Engi 21.05.2024

Sobie machnąłem taką tabele na testowym serwerze

CREATE TABLE `missions` (`uid` INT UNSIGNED NOT NULL AUTO_INCREMENT , `desc` VARCHAR(32) NOT NULL , `goal` INT(1) UNSIGNED NOT NULL , `name` VARCHAR(32) NOT NULL , PRIMARY KEY (`uid`))

 Dodałem do niego dwa rekordy
 

INSERT INTO `missions` (`uid`, `desc`, `goal`, `name`) VALUES (NULL, 'ASDF', '1', 'ASDF');
INSERT INTO `missions` (`uid`, `desc`, `goal`, `name`) VALUES (NULL, 'd*pa', '1', 'd*pa');

Sprawdziłem, jaki jest następny Następny Autoincrement 

SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'XYZ' AND TABLE_NAME = 'missions';

Zwróciło mnie "3" - więcj jest ok.

Następnie podpytałem trochę ejaja co tu się dzieje (skoro ma zabrać moją pracę, to musi się znać na robocie, a ze jest darmowy i ostatnio zrobił progress to czemu nie) i mi zasugerował albo ON DUPLICATE KEY, albo procedurę. Na pytanie jak zapobiec aktualizacji autoincrement powiedział tak

 

Jeśli chcesz uniknąć aktualizacji kolumny id oznaczonej jako AUTO_INCREMENT podczas użycia INSERT ... ON DUPLICATE KEY UPDATE, musisz upewnić się, że ta kolumna nie jest uwzględniona w sekcji UPDATE. W sekcji UPDATE powinny być tylko te kolumny, które chcesz zaktualizować.

 

I dał mi przykład. zmodyfikowałem go pod moje testowe tabele.

INSERT INTO missions (uid, `desc`, `goal`, `name`) VALUES (2, 'example', 1, 'value1') ON DUPLICATE KEY UPDATE `desc` = VALUES(`desc`), `name` = VALUES(`name`);

O dziwo, rekordy zostały zaktualizowane, a `SELECT AUTOINCREMENT` który juz wcześniej zrobiłem nadal zwrócił mi 3.

Więc dodałem następne dwa rekordy, mam pięknie ajdiki 1,2,3,4, więc coś mnie tu nie pasuje  :krecka_dostal:

 

Swoją drogą, postarał się nasz ejaj, bardzo dużo treści wygenerował, łapcie link: https://chatgpt.com/...a1-0cae3b147fca

 

Dałeś się wkręcić tak samo jak ja, uid nie jest auto increment ale random stringiem, on ma osobno id jako auto increment, czyli id, uid, desc, goal, name. Pierwszy sql z pierwszego posta działa jeżeli wrzucisz uid jako unique ale dalej podnosi auto increment bo to innodb, na myisam nie podnosi.


dasiek (21.05.2024 11:50):

LOL

Odpowiedz

  • +
  • -
Robiin - zdjęcie Robiin 21.05.2024

Tak, to prawda. Nie doprecyzowałem, że uid to nie jest to od auto incrementa, tylko mój randomowy string. W każdym razie zrobiłem tak i już tak zostanie:

SQL_PrepareQuery(sql_connection,
        "UPDATE `missions` SET `desc`='%s', `name`='%s', `goal`='%i' WHERE `uid` = '%s';",
        desc, name, goal, uid);

A potem

SQL_PrepareQuery(sql_connection,
        "INSERT INTO `missions` (`uid`, `name`, `desc`, `goal`) \
        SELECT '%s', '%s', '%s', %i \
        WHERE NOT EXISTS ( \
            SELECT 1 \
            FROM `missions` \
            WHERE `uid` = '%s' \
        );",
        uid, name, desc, goal,
        uid);


Swoją drogą, postarał się nasz ejaj, bardzo dużo treści wygenerował, łapcie link: https://chatgpt.com/...a1-0cae3b147fca

Musiałeś podziękować za informację, żeby uniknąć śmierci w 2050 jak już wyjdą pierwsze wersje terminatorów? Mądrze...


dasiek (21.05.2024 15:26):

Dziękuję za pomoc ejaj, dzień dobry mówię zawsze... ja dobry chłopak jestem...

Odpowiedz