Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [MYSQL] IF NOT EXISTS, zapytanie z EXISTS
Tomplus
post
Post #1





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


Witam,

Mam pytanie,

Chciałem skrócić kod i wpadłem na pomysł że to co mogę w paru liniach zrobić w PHP mogę w jednej linii zrobić w MYSQL, ale.... coś nie wychodzi.

Mam nast. zapytanie SQL:
Kod
IF NOT EXISTS
     SELECT `uid`,`link` FROM `link_logs` WHERE `uid` = '67' AND `link` = '0'
  THEN
     INSERT INTO `link_logs` (`uid`, `link`) VALUES ('67', '0')
END IF;


wypróbowałem też zapytanie bez IF:

Kod
INSERT INTO `sm_link_logs` (`uid`, `link`) VALUES ('67', '0')
  WHERE
    NOT EXISTS (
      SELECT `uid`,`link` FROM `sm_link_logs` WHERE `uid` = '67' AND `link` = '0'
    );


Wg. tego co się dowiedziałem to w ten sposób powinno wyglądać zapytanie.
Jednak nie pojawia się żaden błąd MySQL (co sugeruje mi że nie ma błędu parsera w zapytaniu) ale jest błąd logiczny bo mimo że tabela jest pusta, Nie pojawia się nowa liniia.

z założenia jest że jeżeli nie istnieje uid i link o podanych wartościach to ma stworzyć nową wartość w tabeli o takich wartościach.

Wiedzę na ten temat znalazłem tu:
http://forums.mysql.com/read.php?98,33383,33784#msg-33784 oraz
http://lists.mysql.com/replication/220

Prosiłbym o pomoc przy tym zapytaniu.

Ten post edytował Tomplus 12.02.2011, 19:39:55
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 10)
trafas
post
Post #2





Grupa: Zarejestrowani
Postów: 87
Pomógł: 12
Dołączył: 31.05.2006

Ostrzeżenie: (0%)
-----


Witam,

W mysql EXISTS tak prosto się nie używa.
Generalnie raczej wykorzystywane jest w procedurach.

Dla sprawdzenia czy dany wiersz istnieje w tabeli bez proedury możesz wykonać zapytanie:

  1. SELECT IF(NOT EXISTS
  2. (`uid`,`link` FROM `link_logs` WHERE `uid` = '67' AND `link` = '0'),
  3. 'INSERT', -- wartość jeżeli warunek jest spełniony
  4. 'wiersz istnieje' -- wartość jeżeli warunek jest spełniony
  5. );



W przypadku użycia procedury:


  1. DELIMITER //
  2. CREATE PROCEDURE sprawdz(IN uid_in INT, IN link_in varchar(30))
  3. BEGIN
  4.  
  5. IF NOT EXISTS (SELECT 1 FROM `sm_link_logs` WHERE `uid` = uid_in AND `link` = link_in)
  6. THEN
  7. INSERT INTO `link_logs` (`uid`, `link`) VALUES (uid_in, link_in)
  8. ELSE
  9. SELECT 'rekord już istnieje' AS 'komunikat';
  10. END IF;
  11.  
  12. END //
  13. DELIMITER ;


Wywołanie procedury:

  1. call sprawdz(67,'0')


Pozdrawiam.

Ten post edytował trafas 12.02.2011, 20:20:24
Go to the top of the page
+Quote Post
Tomplus
post
Post #3





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


oczywiście procedur nie da się wykonać w zapytaniu MySQL w PHP ?

Jednak jak po sprawdzeniu ma wykonać mi INSERT ?

  1. SELECT IF (NOT EXISTS
  2. (`uid`,`link` FROM `link_logs` WHERE `uid` = '67' AND `link` = '0'),
  3. 'INSERT', (INSERT INTO `link_logs` (`uid`, `link`) VALUES ('67', '0'))
  4. );

czy
  1. SELECT IF (NOT EXISTS
  2. (`uid`,`link` FROM `link_logs` WHERE `uid` = '67' AND `link` = '0')
  3. INSERT INTO `link_logs` (`uid`, `link`) VALUES ('67', '0')
  4. );


Obydwa nie działają u mnie.

móglbym to obejść:
najpierw dać zapytanie SELECT, a potem jeżeli false umieścić INSERT w osobnym zapytaniu, ale nie widzę sensu tworzyć kodu ponad potrzebę.


Osobiście szukam jeszcze rozwiązania:
Znalazłem podobny problem na tym forum:
http://forum.php.pl/index.php?showtopic=103731
Acz dziwi mnie rozwiązanie, bo jest polecane zapytanie z użyciem INSERT IGNORE, ale to nie da mi rozwiązania, bo utworzy kolejny wpis, bo prócz uid i link jest jeszcze unikatowa kolumna 'datatime' oraz id
Go to the top of the page
+Quote Post
trafas
post
Post #4





Grupa: Zarejestrowani
Postów: 87
Pomógł: 12
Dołączył: 31.05.2006

Ostrzeżenie: (0%)
-----


Pierwszy przykład nie umożliwi Ci wprowadzenia danych. Pokazałem Ci tylko sposób, jak skorzystać z polecenia EXISTS poza procedurą.

Do wprowadzenia zmian możesz użyc funkcji lub procedury.
Z poziomu PHP procedurę wykonujesz zapytaniem:

  1. mysql_query("CALL nazwa_procedury");


funkcję wykonujesz przez wykonaie zapytania:

  1. mysql_query("SELECT nazwa_funkcji");


Funkcja do sprawdzenia istnienia wiersza i przy jego braku wpisanie go do bazy:


  1. DELIMITER //
  2. CREATE FUNCTION sprawdz(uid INT, link varchar(30)) RETURNS VARCHAR(50)
  3. BEGIN
  4.  
  5. IF NOT EXISTS (SELECT 1 FROM `sm_link_logs` WHERE `uid` = uid_in AND `link` = link_in)
  6. THEN
  7. INSERT INTO `link_logs` (`uid`, `link`) VALUES (uid_in, link_in);
  8. RETURN 'rekord został dopisany';
  9. ELSE
  10. RETURN 'rekord już istnieje';
  11. END IF;
  12.  
  13. END //
  14. DELIMITER ;


Wykonanie w PHP:

  1. $query = "select sprawdz(67,'0')";
  2. $data = mysql_query($query) or die (mysql_error());
  3. $dane = mysql_fetch_array($data);
  4. echo "Wynik działania funkcji : ".$dane[0];


Pozdrawiam.

Ten post edytował trafas 13.02.2011, 15:00:03
Go to the top of the page
+Quote Post
Tomplus
post
Post #5





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


Bardzo ładnie, tylko nie działa... :/
Tzn. pewnie działa, tylko nadal nie rozumiem jednego...

Samo wykonanie w PHP jest proste i sam do tego doszedłem, tylko problem tkwi jak mam stworzyć tą procedurę lub funkcję ?
Skąd zapytanie SQL wczyta funkcję sprawdz() ?


  1. $query = "select sprawdz(67,'0')";
  2. $data = mysql_query($query) or die (mysql_error());



Przeszukałem trochę googla i nie znazlłem w jaki sposób mam przechowywać procedury do późniejszego użycia.
Proszę o radę.


Ten post edytował Tomplus 13.02.2011, 15:51:58
Go to the top of the page
+Quote Post
trafas
post
Post #6





Grupa: Zarejestrowani
Postów: 87
Pomógł: 12
Dołączył: 31.05.2006

Ostrzeżenie: (0%)
-----


Po wykonaniu kodu tworzącego procedurę czy funkcję trzymane są one w bazie danych.

Jak stworzysz procedurę to póżniej możesz z niej korzystać do woli.

Aby sprawdzić listę procedur/funkcji wykonujesz:

  1. SHOW FUNCTION STATUS
  2. -- lub
  3. SHOW procedure STATUS
Go to the top of the page
+Quote Post
Tomplus
post
Post #7





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


Wykonuje więc w moim PHPMyAdmin kod:


  1. DELIMITER //
  2. CREATE FUNCTION sprawdz(uid INT, link TINYINT) RETURNS TINYINT
  3. BEGIN
  4.  
  5. IF NOT EXISTS (SELECT 1 FROM `link_logs` WHERE `uid` = uid_in AND `link` = link_in)
  6. THEN
  7. INSERT INTO `link_logs` (`uid`, `link`) VALUES (uid_in, link_in);
  8. RETURN 'rekord zostal dopisany';
  9. ELSE
  10. RETURN 'rekord juz istnieje';
  11. END IF;
  12.  
  13. END //
  14. DELIMITER ;


W pierwszym zapytaniu, zwraca mi błąd że nie potrafi zrozumieć DELIMITER, usuwam wraz // (bo dowiedziałem się że to działa jak średnik)

Ale po tym też zwraca mi błąd, nie zrozumienia zapytania,
Go to the top of the page
+Quote Post
#luq
post
Post #8





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Cytat(Tomplus @ 13.02.2011, 18:52:45 ) *
W pierwszym zapytaniu, zwraca mi błąd że nie potrafi zrozumieć DELIMITER, usuwam wraz // (bo dowiedziałem się że to działa jak średnik)

Zapisz to w pliku i odpal przez konsole.

Natomiast Tobie najprawdopodobniej chodzi o niepowtarzanie pewnych danych a więc ustaw sobie klucz UNIQUE `uid` i `link`. Wtedy nie ma opcji żebyś miał w bazie dwa rekordy o identycznych wartościach w tych polach.

Go to the top of the page
+Quote Post
Tomplus
post
Post #9





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


Nie mam konsoli do MySQL, bo jedyny dostęp do serwera MySQL to PHPMyAdmin, lub polecenia z plików PHP

Natomiast co do porady, to jest nie trafiona. Wartości uid i link się mogą powtórzyć, ale nie mogą się powtórzyć w tej samej kombinacji.

Czyli:
67 0
67 1
13 0
12 1
itp...
Gdybym dał UNIQE to zwracałoby mi błąd za kazdym razem gdy powtórzył się uid, nawet jeżeli jest inny link.
Go to the top of the page
+Quote Post
#luq
post
Post #10





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Cytat(Tomplus @ 13.02.2011, 19:20:48 ) *
Nie mam konsoli do MySQL, bo jedyny dostęp do serwera MySQL to PHPMyAdmin, lub polecenia z plików PHP

A więc exec chodź podejrzewam, że możesz mieć tą funkcje zablokowaną na serwerze.

Cytat
Gdybym dał UNIQE to zwracałoby mi błąd za kazdym razem gdy powtórzył się uid, nawet jeżeli jest inny link.

Jesteś tego pewien? Sprawdzałeś?
Go to the top of the page
+Quote Post
Tomplus
post
Post #11





Grupa: Zarejestrowani
Postów: 1 879
Pomógł: 230
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


Cytat(#luq @ 13.02.2011, 19:29:02 ) *
A więc exec chodź podejrzewam, że możesz mieć tą funkcje zablokowaną na serwerze.

Owszem.

Cytat(#luq @ 13.02.2011, 19:29:02 ) *
Jesteś tego pewien? Sprawdzałeś?

To było sprytne (IMG:style_emoticons/default/smile.gif)
W pierwszej chwili zrozumiałem że należy dać UNIQUE dla uid i link, ale osobno dla kolumn.
ale nie zwróciłem uwagi na to że wartość UNIQUE może być współdzielona.


Dziękuje #luq, może wynik nie jest taki jak zapytałem, ale rozwiązanie jest bardzo dobre.

Dziekuje również trafas'owi, mimo że Twoje rady nie dało się wykorzystać przy moich uprawnieniach.

Ten post edytował Tomplus 13.02.2011, 19:47:18
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 14:03