Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wyzwalacz - tworzenie unikalnego identyfikatora
Forum PHP.pl > Forum > Bazy danych > MySQL
Mephis
Witam.

Chciałbym stworzyć wyzwalacz, który byłby aktywowany przed poleceniem INSET do tabeli, a jego celem byłoby stworzenie unikalnego identyfikatora.
Wyzwalacz miałby za zadanie wylosowanie liczby z zakresu od 10000 do 65535 i sprawdzenie, czy w tabeli istnieje już taki identyfikator. Następnie wylosowany ciąg liczb zapisał jako nowy identyfikator. Wiem, że mógłbym użyć tutaj autoinkrementacji, ale nie chcę, by po identyfikatorze można było stwierdzić ilość rekordów w tabeli i chciałbym, żeby każdy identyfikator miał taką samą ilość cyfr.

Poniżej mam tylko zarys tego, jak wydaje mi się, że mogłoby to wyglądać. Problem pojawia się niestety tuż przy deklaracji zmiennej, albowiem jakakolwiek próba przypisania wartości do niej wartości kończy się niezbyt jasnym dla mnie błędem w rodzaju "#1064 - check the manual that corresponds to your MySQL server version for the right syntax to user near '' at line 4" a jeżeli już mi się uda, to ten sam błąd będzie dotyczyć tego, co znajdzie się pod deklaracją zmiennych.
  1. DROP TRIGGER IF EXISTS `wyzwalacz`;
  2. CREATE DEFINER=`root`@`localhost` TRIGGER `wyzwalacz` BEFORE INSERT ON `tabela` FOR EACH ROW
  3. BEGIN
  4.  
  5. SET @rand = ROUND((RAND() * 55534 + 10000), 0);
  6.  
  7. WHILE ((SELECT `id` FROM `tabela` WHERE `id` = @rand) == @rand) DO
  8. SET @rand = ROUND((RAND() * 55534 + 10000), 0);
  9. END;
  10.  
  11. SET new.id = @rand;
  12.  
  13. END;

Rozumiem, że gdzieś tutaj tkwi podstawowy błąd, ale ja już sam nie wiem gdzie on jest, skoro błędy tego rodzaju wyskakują mi nawet po kopiowaniu przykładów z manuala.
kartin
Cytat(Mephis @ 15.10.2015, 22:50:39 ) *
"#1064 - check the manual that corresponds to your MySQL server version for the right syntax to user near '' at line 4" a jeżeli już mi się uda, to ten sam błąd będzie dotyczyć tego, co znajdzie się pod deklaracją zmiennych.
  1. DROP TRIGGER IF EXISTS `wyzwalacz`;
  2. CREATE DEFINER=`root`@`localhost` TRIGGER `wyzwalacz` BEFORE INSERT ON `tabela` FOR EACH ROW
  3. BEGIN
  4.  
  5. SET @rand = ROUND((RAND() * 55534 + 10000), 0);
  6.  
  7. WHILE ((SELECT `id` FROM `tabela` WHERE `id` = @rand) == @rand) DO
  8. SET @rand = ROUND((RAND() * 55534 + 10000), 0);
  9. END;
  10.  
  11. SET new.id = @rand;
  12.  
  13. END;

Rozumiem, że gdzieś tutaj tkwi podstawowy błąd, ale ja już sam nie wiem gdzie on jest, skoro błędy tego rodzaju wyskakują mi nawet po kopiowaniu przykładów z manuala.


Słabo czytałeś manuala ;P
Jeśli wykonujesz zapytania w takiej formie jak to przedstawiane, to rzeczywiście jest podstawowy błąd składni. Średnik standardowo jest traktowany jako koniec zapytania. Zatem tutaj jest 6 zapytań zamiast 2.

Trzeba zmienić znak końca zapytania
  1. DELIMITER //
  2.  
  3. DROP TRIGGER IF EXISTS `wyzwalacz`//
  4.  
  5. CREATE TRIGGER `wyzwalacz` BEFORE INSERT ON `tabela` FOR EACH ROW
  6. BEGIN
  7. ...
  8. END //
  9.  
  10. DELIMITER ;
Mephis
Czyli chodzi o ten DELIMITER. O dziwo kod który napisałem działa jak należy...

Dla testów obniżyłem zakres do paru wolnych miejsc. Gdy się one wszystkie zapełniły, nastąpiła nieskończona pętla. Pytanie mam następujące: w jaki sposób przerwać wtedy cały skrypt, łącznie z zapytaniem INSET dla którego wykonywany jest wyzwalacz? No i jak optymalnie sprawdzić, czy te miejsca są już zapełnione (zliczanie rekordów w bazie przy każdej pętli to chyba kiepski pomysł)?

A tak przy okazji; istnieje jakaś funkcja, która zwróciłaby mi długość/rozmiar pola, albo jeżeli to int to żeby zwróciła maksymalną liczbę, którą pole może przyjąć?
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.