Cómo ejecutar 'SELECCIONAR PARA ACTUALIZAR' en Laravel 3 / MySQL
Frecuentes
Visto 2,181 veces
2
Estoy tratando de ejecutar SELECCIONAR ... PARA ACTUALIZAR consulta usando Lavable 3:
SELECT * from projects where id = 1 FOR UPDATE;
UPDATE projects SET money = money + 10 where id = 1;
I have tried several things for several hours now:
DB::connection()->pdo->exec($query);
y
DB::query($query)
También he intentado agregar START TRANSACTION; ... COMMIT;
to the query
and I tried to separate the SELECT
del desplegable UPDATE
in two different parts like this:
DB::query($select);
DB::query($update);
Sometimes I get 0 rows affected, sometimes I get an error like this one:
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
SQL: UPDATE `sessions` SET `last_activity` = ?, `data` = ? WHERE `id` = ?
I want to lock the row in order to update sensitive data, using Laravel's database connection.
Gracias.
3 Respuestas
5
In case all you need to do is increase money
by 10
, you don't need to lock the row before update. Simply executing the update query will do the job. The SELECT
query will only slow down your script and doesn't help in this case.
UPDATE projects SET money = money + 10 where id = 1;
Respondido el 06 de diciembre de 13 a las 21:12
Why I don't need to lock the row? What happens when multiple queries (let say 50) run at the same time? how can I be sure the values are 100% up-to-date, accurate and secure without locking the row? - Jonathan
If you run just an UPDATE
query, it's always going to increment the number by one, no matter what the number is before update. The updates in mysql are done sequentially, no need to lock the row. It would be a different story if you'd have to work with the money value, for example first SELECT money FROM projects WHERE id=1
, entonces UPDATE money = money + 10
y luego INSERT INTO log (money, project_id, time) VALUES ($select['money'], 1, NOW())
to log when the money changed to what value. In this case you'd have to lock the row either by SELECT ... FOR UPDATE
or UPDATE..
- micro
4
- I would use diferent queries for sure, so you can have control on what you are doing.
I would use a transaction. If we read this simple explanations, pdo transactions are quite straightforward. They give us this simple but complete example, that ilustrates how everithing is as we should expect (consider
$db
Ser tuDB::connection()->pdo
).try { $db->beginTransaction(); $db->exec("SOME QUERY"); $stmt = $db->prepare("SOME OTHER QUERY?"); $stmt->execute(array($value)); $stmt = $db->prepare("YET ANOTHER QUERY??"); $stmt->execute(array($value2, $value3)); $db->commit(); } catch(PDOException $ex) { //Something went wrong rollback! $db->rollBack(); echo $ex->getMessage(); }
Lets go to your real statements. For the first of them, the
SELECT ...
, i wouldn't useexec
, peroquery
, since as stated aquíPDO::exec() does not return results from a SELECT statement. For a SELECT statement that you only need to issue once during your program, consider issuing PDO::query(). For a statement that you need to issue multiple times, prepare a PDOStatement object with PDO::prepare() and issue the statement with PDOStatement::execute().
And assign its result to some temp variable like
$result= $db->query ($select);
After this execution, i would call
$result->fetchAll()
o$result->closeCursor()
, since as we can read aquíIf you do not fetch all of the data in a result set before issuing your next call to PDO::query(), your call may fail. Call PDOStatement::closeCursor() to release the database resources associated with the PDOStatement object before issuing your next call to PDO::query().
Entonces tú puedes
exec
la actualización$result= $db->exec($update);
And after all, just in case, i would call again
$result->fetchAll()
o$result->closeCursor()
.
Respondido el 10 de diciembre de 13 a las 21:12
1
If the aim is
to lock the row in order to update sensitive data, using Laravel's database connection.
Maybe you can use PDO transactions :
DB::connection()->pdo->beginTransaction();
DB::connection()->pdo->commit();
DB::connection()->pdo->rollBack();
Respondido el 05 de diciembre de 13 a las 13:12
Is the first query executed correctly when you get the error "update
sessions
SET (...)"? - QullbruneWhen you use DB::query() with a SELECT, PDO expects you to exhaust the buffer before the next query. So use DB::query($select)->closeCursor() or DB::connection()->pdo->exec($select) to avoid the SQL error. - ColinM
could you try my solution below? i keep coming to check if it worked or not! - Carlos Robles
@colinm, FYI your comment is just a fragment of an answer you can read from a day before. - Carlos Robles