2013-08-03 17 views
21

Dostaję błąd "SQLSTATE [HY093]: nieprawidłowy numer parametru" kiedy próbuję uruchomić poniższą funkcję:PHP PDOException: "SQLSTATE [HY093]: nieprawidłowy numer parametru"

function add_persist($db, $user_id) { 
    $hash = md5("per11".$user_id."sist11".time()); 
    $future = time()+(60*60*24*14); 
    $sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash"; 
    $stm = $db->prepare($sql); 
    $stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future)); 
    return $hash; 
} 

czuję jak to jest coś prostego, czego po prostu nie łapię. Jakieś pomysły?

+9

'Nie można używać nazwanego markera parametru o tej samej nazwie dwa razy w przygotowanym oświadczeniu." [Http://php.net/manual/en/pdo.prepare.php](http://php.net/ manual/en/pdo.prepare.php) – bitWorking

+0

Rozumiem, że ten post ma odpowiedź, która również odpowiada na moje pytanie, ale moje pytanie zdecydowanie nie jest możliwym duplikatem. – vijrox

+0

W drugim pytaniu 'fetchAll()' nie zwraca nic, ponieważ zapytanie nie powiodło się tak samo jak twoje. Drugi autor po prostu tego nie zauważył. Jest to zasadniczo ten sam problem, więc warto połączyć te dwa. – RandomSeed

Odpowiedz

33

Spróbuj:

$sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash2"; 

i

$stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future, ":hash2" => $hash)); 

Wyciąg z dokumentacji (http://php.net/manual/en/pdo.prepare.php):

musi zawierać unikalny znacznik parametru dla każdej wartości, które chcą przekazać w do instrukcji, gdy wywołasz funkcję PDOStatement :: execute(). Nie można używać nazwanego znacznika parametru o tej samej nazwie dwa razy w przygotowanej instrukcji. Nie można powiązać wielu wartości z jednym nazwanym parametrem w, na przykład, klauzuli IN() instrukcji SQL.

+0

zadziałało! Przyjmuję twoją odpowiedź, gdy tylko stos mi pozwoli. Dlaczego oryginalna metoda nie działa? – vijrox

+0

@VijayRamamurthy, przeczytaj proszę: http://php.net/manual/en/pdo.prepare.php – vee

+0

Jaka jest różnica między twoją odpowiedzią a pytaniem OP? – Shafizadeh

15

Jest to jedno ograniczenie do korzystania z PDO. PDO po prostu potwierdza liczbę parametrów w zapytaniu i wykonaniu i zgłasza błąd w przypadku niezgodności. Jeśli trzeba użyć parametru powtórzenia w zapytaniach, trzeba zabrać za pomocą obejścia

$sql = "insert into persist(user_id, hash, expire) values 
    (:user_id, :hash, :value) on duplicate key update 
    hash = :hash2"; 
$stm->execute(array(':user_id' => $user_id, ':hash' => $hash, ':hash2' => $hash, 
    ':expire' => $expire)); 

Można odwołać się do tego bardziej skomplikowanego obejścia - https://stackoverflow.com/a/7604080/1957346

+1

Awesome! Spędziłem dwa dni na debugowaniu kodu, który działał na wszystkim innym poza jednym konkretnym zapytaniem. Odpowiedź była (jak wspomniano w powyższym "vijrox"), że nie można ponownie użyć tego samego nazwanego parametru w PDO. Miałem "UPDATE users SET username =: username, caption =: caption WHERE nazwa_użytkownika =: username', które nie zadziała, ponieważ': username' pojawia się dwa razy. Poprawka polegała na zmianie nazwy drugiego, kończąc na tym: 'UPDATE users SET username =: username, caption =: caption WHERE username =: user' (ostatnie': user' jest inne). –

-2
$stmt = $con->prepare("INSERT INTO items(Name, Description, Price, Country_Made, Status, Add_Date) VALUES(:zname, :zdesc, :zprice, :zcountry, zstatus, now())"); 

$stmt-> execute(array(
    "zname" => $name, 
    "zdesc" => $desc, 
    "zprice" => $price, 
    "zcountry" => $country, 
    "zstatus" => $status 
)); 
+2

Należy zawsze dodawać wyjaśnienia do kodu ... – andreas

+0

Mimo że ten kod może pomóc w rozwiązaniu problemu, nie wyjaśnia on, dlaczego _why_ i/lub _how_ to odpowiada na pytanie.Zapewnienie tego dodatkowego kontekstu znacznie poprawiłoby jego długoterminową wartość edukacyjną. Proszę [edytuj] swoją odpowiedź, aby dodać wyjaśnienie, w tym, jakie ograniczenia i założenia mają zastosowanie. –

2

wiem, że to stare pytanie, ale myślę, że warto zauważyć, że właściwszym rozwiązaniem byłoby uniknąć przylegający obejścia w PHP wykorzystując SQL odpowiednio:

INSERT INTO `persist` (`user_id`, `hash`, `expire`) 
VALUES (:user_id, :hash, :expire) 
ON DUPLICATE KEY UPDATE `hash`=VALUES(`hash`) 

W ten sposób wystarczy wysłać wartość tylko raz.

Powiązane problemy