Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL]Dodawanie rekordu jeżeli nie istnieje
Forum PHP.pl > Forum > Przedszkole
Dukov
Tak jak w temacie, chcę dodać do bazy rekord, jeżeli ten nie istnieje, a jeżeli istnieje zwrócić false, próbowałem już setki rozwiązań z stackoverflow i za każdym razem wywala błąd
  1. SELECT CASE WHEN EXISTS (
  2. SELECT *
  3. FROM users
  4. WHERE login = :login
  5. OR
  6. mail = :mail
  7. )
  8. THEN
  9. INSERT INTO users (login,mail,name,city,avatar,ip_addr,reg_date,last_log_date,active,permissions,famous,rang,banned,warns) VALUES (:login,:mail,:password,0,0,"$ip","$date",0,0,0,0,0,0,0, ))
  10. ELSE
  11. CAST(0 AS BIT) END

albo to:
  1. INSERT INTO users (login,mail,password,name,city,avatar,ip_addr,reg_date,last_log_date,active,permissions,famous,rang,banned,warns) VALUES (:login,:mail,:password,0,0,0,"$ip","$date",0,0,0,0,0,0,0 )
  2. SELECT DISTINCT login
  3. FROM users
  4. WHERE
  5. NOT EXISTS (SELECT 1 FROM users
  6. WHERE login = :login)
  7.  
  8.  
  9.  
  10.  
  11.  
viking
Złap wyjątek dla insert i zamień sobie wtedy odpowiedź na false.
Dukov
A możesz nieco jaśniej? Bazy danych to zdecydowanie nie jest moja mocna strona, zresztą dlatego teraz pisze, żeby podszlifować umiejętności.
viking
  1. try {
  2. zapytanie insert które w przypadku zduplikowania danych (maila lub loginu) zwróci wyjątek
  3. } catch (\PDOException $e) {
  4. return false;
  5. }
Dukov
No dobrze, rozumiem o co chodzi, tylko jak mam zwrócić ten wyjątek. zresztą wolałbym zrobić to w jednym zapytaniu, bo mam obiekt z metodami odnoszącymi się do bazy danych, a w tych metodach chcę tylko dołaczać zapytanie jako file_get_contents, żeby nie było pomieszanych zapytań z PHP, bo będzie to nieczytelne.
Konkretnie mam wysyłany json przez ajax do pliku controller.php, w nim switcha i dołączanie odpowiednicyh plików, jeżeli dane przejdą przez walidacje, to tworzy obiekt wspomnianej bazy danych, a zapytania są w folderze queries.
viking
Sposób dołączania zapytania nie ma żadnego znaczenia. Błędne zapytanie spowodfuje automatyczne rzucenie wyjątku - dla PDO $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
vokiel
Nie wystarczy
Kod
INSERT IGNORE ...
?

A jeśli już z łapaniem Exception, to trzeba sprawdzić jaki to jest wyjątek - żeby w ten sam sposób nie obsługiwać wszystkich.
viking
Czyli według Ciebie lepsze będzie zignorowanie? To wygląda na rejestrację. Nie ma znaczenia jaki błąd sypnie baza. Ważny jest efekt końcowy czyli brak rekordu.
mmmmmmm
Wytłumaczę ci najprościej jak się da. Baza danych porównuje zbiory. Zbiór twoich danych wejściowych (daną wejściową jest rekord) ze zbiorem danych z tabeli.
Utwórz sobie taki zbiór i go go porównaj z tabelą. Jesli go nie znajdzie, to wtedy dodaj.
Czyli po kolei
Utworzenie zbioru jednoelementowego:
  1. SELECT :login AS login, :mail AS mail, :password AS pass, :ip AS ip, :DATA AS date

Teraz sprawdzasz, czy danych zbiór istnieje. Warunkiem istnienia jest klucz, czyli w tym przypadku login. Jak najłatwiej sprawdzić? Połączyć lewostronnie po kluczu i sprawdzić, czy w drugiej tabeli znalazł dany rekord.
  1. SELECT * FROM
  2. (SELECT :login AS login, :mail AS mail, :password AS pass, :ip AS ip, :DATA AS date) AS sub
  3. LEFT JOIN
  4. users AS u
  5. ON u.login=sub.login
  6. WHERE
  7. u.login IS NULL

Jeśli zapytanie zwróci ci jakikolwiek rekord (a może zwrócić tylko jeden), to wtedy dodajesz go do `users`. Zapytanie jest o tyle bezpieczne, że możesz je wykonywać ile razy chcesz - rekord doda się tylko raz (bo za każdą następną próbą już będzie)
  1. INSERT INTO users(login, mail, pass, ip, date)
  2. SELECT sub.* FROM
  3. (SELECT :login AS login, :mail AS mail, :password AS pass, :ip AS ip, :DATA AS date) AS sub
  4. LEFT JOIN
  5. users AS u
  6. ON u.login=sub.login
  7. WHERE
  8. u.login IS NULL
Pyton_000
Ło matko.. najlepiej jak by napisać do tego jeszcze jakiś mikroserwis który będzie to sprawdzał...


Do Autora tematu. Załóż 2 indeksy Unique w Bazie na pola `email` i `username` i wykonuj normalny INSERT bez żadnych pierdoł.

W przypadku próbu wrzucenia rekordu nie unikalnego po prostu się nie stworzy a PDO wyrzuci Exceprion który musisz złapać.

Tu masz przykład:
Kod
try {
  $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer)    VALUES (NULL, :name, :password, :question, :answer)");
  $stmt->bindValue(":name", $_POST['name']);
  $stmt->bindValue(":password", $_POST['password']);
  $stmt->bindValue(":question", $_POST['question']);
  $stmt->bindValue(":answer", $_POST['answer']);
  $stmt->execute();
  echo "Successfully added the new user " . $_POST['name'];
} catch (PDOException $e) {
  echo "DataBase Error: The user could not be added.<br>".$e->getMessage();
} catch (Exception $e) {
  echo "General Error: The user could not be added.<br>".$e->getMessage();
}
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.