Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ MySQL _ INSERT z SELECTem jako prepare

Napisany przez: Jdwind 18.01.2021, 21:47:48

Czy istnieje możliwość przygotowania takiego zapytania jako prepare i bind_param:

  1. $result = $stmt->query("INSERT INTO numery (numer,gid,mid) SELECT IFNULL(MAX(numer), 0)+1, $last_id, $mid FROM numery WHERE YEAR((nr_daty)) = YEAR(NOW())");

Nie mam pojęcia, jak ująć ten SELECT.

Napisany przez: trueblue 18.01.2021, 22:27:31

A jak chcesz inaczej ująć? Zapytanie jest poprawne, wystarczy bindować wartości.

P.S. YEAR((nr_daty)) tu nie jest potrzebny podwójny nawias. A zamiast YEAR(NOW()) warto również bindować rok.

Napisany przez: Jdwind 19.01.2021, 00:56:50

Dziękuję, faktycznie nie zauważyłem tych podwójnych nawiasów. Co do bindowania, nie bardzo mam doświadczenie, mógłbym prosić o podpowiedź? Obecne zapytanie działa, ale wszędzie pisze, żeby bindować bo to bezpieczniejsze. Czy coś takiego będzie poprawne:

  1. $result = $smtp->prepare("INSERT INTO numery (numer,gid,mid) VALUES (SELECT IFNULL(MAX(numer), 0)+1,?,? FROM numery WHERE YEAR(nr_daty) = YEAR(NOW())"));
  2. $result->bind_param('ii', $last_id, $mid);

Napisany przez: trueblue 19.01.2021, 09:25:55

A sprawdzałeś? To najlepsza metoda nauki.

P.S. Jeśli wcześnie używałeś zmiennej $stmt, to pewnie tu też powinieneś.

Napisany przez: Jdwind 20.01.2021, 01:13:35

Niestety, otrzymuję komunikat o błędzie: Call to a member function bind_param() on boolean in /var/www/html... próbowałem zmienić z "i" na "s", też nic.

Napisany przez: viking 20.01.2021, 08:00:19

Czyli mówi ci to że prepare zwróciło false. Masz w ogóle połączenie z bazą?

Napisany przez: Jdwind 20.01.2021, 08:20:21

Tak, tu na pewno jest wszystko w porządku, bo robię to w transakcji. Pierwsze zapytanie - prosty insert, też z prepare - przechodzi, natomiast tu daje błąd. Czy ta moja składnia zapytania jest poprawna? Bo tu właśnie mam wątpliwości.

  1. INSERT INTO numery (numer,gid,mid) VALUES (SELECT IFNULL(MAX(numer), 0)+1,?,? FROM numery WHERE YEAR(nr_daty) = YEAR(NOW())

w "zwykłym" zapytaniu nie miałem VALUES i działało:
  1. INSERT INTO numery (numer,gid,mid) SELECT IFNULL(MAX(numer), 0)+1, $last_id, $mid FROM numery WHERE YEAR((nr_daty)) = YEAR(NOW())

Dlatego właśnie napisałem, że nie do końca rozumiem jeszcze 'prepare' przy takim złożonym zapytaniu.

Napisany przez: trueblue 20.01.2021, 08:23:02

A nazwa zmiennej to $smtp czy $stmt?

Napisany przez: LowiczakPL 20.01.2021, 08:23:07

masz

INTO numery (numer, gid, mid)

Czy przekazujesz prawidłowe typy zmiennych do tych 3 pól?


Napisany przez: Jdwind 20.01.2021, 11:38:41

A nazwa zmiennej to $smtp czy $stmt? - źle przepisałem, przepraszam, nazwy zmiennych mam poprawne.
Czy przekazujesz prawidłowe typy zmiennych do tych 3 pól? - no i tu chyba jest mój problem, bo preparuję niejako dwie ostatnie zmienne, trzecią powinien brać z SELECTa, ale chyba źle skonstruowałem zapytanie. Natomiast tamte dwie próbowałem już jako integer i jako string, niestety ten sam błąd.

Napisany przez: trueblue 20.01.2021, 11:45:38

INSERT INTO numery (numer,gid,mid) VALUES (SELECT IFNULL(MAX(numer), 0)+1 FROM numery WHERE YEAR(nr_daty) = YEAR(NOW()),?,?)

P.S. Bardzo prawdopodobne, że trzeba też dodać alias do tabeli w podzapytaniu SELECT.

Napisany przez: Jdwind 20.01.2021, 23:02:12

Zadziałało w końcu w takiej formie:

  1. INSERT INTO numery (numer,gid,mid) SELECT IFNULL(MAX(numer), 0)+1,?,? FROM numery WHERE YEAR(nr_daty) = YEAR(NOW());

czyli bez VALUES (czego do końca akurat nie rozumiem). W każdym bądź razie działa, dziękuję kolegom za pomoc.
EDIT:
A jeszcze jedno pytanie - czy przy "zwykłym" SELECT też używać bindowania, czy np. tylko wtedy, jeśli w zapytaniu mam zmienną pobraną z formularza?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)