PDO execute statement hangs - php

I have a problem when calling execute on a prepared statement using PDO.
Here is my code:
$db = Connection::getConnection();
$query = 'INSERT INTO stories (st_title, st_authors, st_content, st_cover) VALUES (?,?,?,?)';
$params = ['title', 'Authors', 'content', 'cover'];
$stmt = $db->prepare($query);
echo "before <br>";
$stmt->execute($params);
echo "after <br>";
If I comment out the line $stmt->execute($params);, both "before" and "after" show up. However, if I leave it uncommented, neither of them show up.
I have also tried using bindParam() instead of executing with an array, but I got the same result.
It's also worth taking note that inserting into the database, with the exact same parameters, from sqlPlus works flawlessly.
I am running an oracle 11g database server locally.
Any help would be highly appreciated, I've been stuck on this for a while now.
Edit: I mentioned it in the title, but forgot to mention it here too. When this code runs, the server hangs indefinetely and I am forced to restart apache.
Edit2: The connection is ok, and I figured out the source of the problem.
On the stories table, i have an unique constraint on st_title.
The problem occurs when i try to insert a story with the same title as a previous one AFTER that previous one has been DELETED.
If I remove the unique constraint, the problem goes away.
However I would like to keep that constraint. Any ideas as to what could cause this?
Edit3: The triggers I have on the stories table:
--auto-increment on st_id--
DROP SEQUENCE stories_id_seq;
CREATE SEQUENCE stories_id_seq;
CREATE OR REPLACE TRIGGER stories_id_auto_inc
BEFORE INSERT ON stories
FOR EACH ROW
BEGIN
SELECT stories_id_seq.NEXTVAL
INTO :new.st_id
FROM dual;
END;
/
--auto-completion for st_date_added--
CREATE OR REPLACE TRIGGER stories_date_added
BEFORE INSERT ON stories
FOR EACH ROW
BEGIN
SELECT sysdate
INTO :new.st_date_added
FROM dual;
END;
/
CREATE OR REPLACE TRIGGER stories_delete
BEFORE DELETE
ON stories
FOR EACH ROW
DECLARE
BEGIN
DELETE FROM st_cat
WHERE st_id = :old.st_id;
-- DELETE FROM characters
-- WHERE st_id = :old.st_id;
DELETE FROM favourites
WHERE st_id = :old.st_id;
DELETE FROM bookmarks
WHERE st_id = :old.st_id;
DELETE FROM comments
WHERE st_id = :old.st_id;
DELETE FROM ratings
WHERE st_id = :old.st_id;
END;
/
The last one is the only relevant one, I think, but i posted them all, just in case.
It's worth noting that the problem only occurs with PDO. If i do the same operations from sqlplus, it works fine.
SOLVED: As it turns out, it wasn't a problem with my code, it was simply the fact that I didn't do a commit; in sqlplus after deleting the rows, and PDO dis weird things with them. (It didn't just show me the normal "title is already taken" message, which is what fooled me).

Probably your Database Connection is not setup correctly.
Take a look at this post to check if your connection is stable and you can succesful perform queries to it.
PDO Connection Test

Related

SELECT and INSERT not selecting

When I execute
INSERT INTO `survey`
(`id`,`name`,`date_start`,`date_end`)
values
(:id,:name,NULL,DATE_ADD(NOW(), INTERVAL 1 MINUTE))
on duplicate key UPDATE `name`=:name;
SELECT coalesce(:id,LAST_INSERT_ID()) as 'id'
it inserts a new data fine, but doesn't select the id (which is needed later on in my php code)
I've tried this suggestion
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
but this SQL throws errors (due to duplicate parameters)
SELECT ASCII(substr(`perm` FROM floor(:i/8)+1))&(1<<(:i%8))>0 as perm FROM `user` WHERE `id`=:id
I'm in a lose-lose situation, re-writing all my SQL code to not have duplicate parameters would be very messy, doing a separate select straight after inserting may not return the id I want. Any suggestions would be great
You cannot run two queries at the same time, only one at the time.
If you want to do the whole thing at once then create a stored procedure.
Same goes for complex queries, when it gets complicated you want to have your logic in the database.
Here is an example:
DELIMITER //
CREATE PROCEDURE sp_insert_survey(IN `p_id`,
IN `p_name`,
IN `p_date_start`,
IN `p_date_end`)
BEGIN
INSERT INTO `survey`(`id`,`name`,`date_start`,`date_end`)
VALUES (p_id, p_name, p_date_start, p_date_end);
SELECT `id`,`name`,`date_start`,`date_end`
FROM survey WHERE `id` =LAST_INSERT_ID();
END //
DELIMITER ;
Call the sp from PDO:
$stmt = $db->prepare('CALL sp_insert_survey(?, ?, ?, ?)');
then fetch the data as a SELECT query.
Upon typing this up, one of the similar questions that came up on the right getting last inserted row id with PDO (not suitable result) gave a suitable answer in the question itself, although I'm a little dubious considering the method is being questioned itself.
$db->lastInsertId();
Seems to work for me, but in the question linked it isn't working as desired for the questioner, so I'm not entirely settled with this answer. It does seem to be a bit of a hack.

MySQL, PHP and failing UPDATE Command

I am experiencing something so basic, yet so annoying that I thought I had to put it out to the wider community to save my sanity.
I am using a table within a database to store some very basic data. There is only two columns, Id and Campaign. I only want to use a single row of the table, however, campaign will be updated at various points. I have set up the table as follows:
$sql = "CREATE TABLE IF NOT EXISTS TestCampaign(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Campaign CHAR(20))";
Initially I write to the table to insert a null CHAR in campaign:
$sql = "INSERT INTO TestCampaign (Campaign) VALUES ('None')";
The based on a specific text field being filled in on an html form followed by a submit button press I intended to do the update of the campaign field:
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
$Test is the POSTED campaign name from the form. Unfortunately although the INSERT works fine the UPDATE doesn't. I have checked the permissions and I have ALL on this database. I have also checked the syntax with various sites and it seems that it is fine.
Interestingly I do not get an error when I echo:
echo " ".mysqli_error($con);
I'm sure I have made some basic error somewhere but I have been looking at it for so long and changing the syntax that I can't seem to spot it.
Any help would be appreciated.
UPDATE:
I have played around with the code and it seems as though the UPDATE code does work, however, It only works when it is the next line of code after the INSERT. In fact I have found that it works as long as it is not where I need it to be. I have it placed in 'if' statement that is run only on a specific button press on the form:
if(isset($_POST['TestID']))
{
Some Code;
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
Some More Code;
}
I have checked the rest of the code in the 'if' statement and it seems solid.
Is this odd behaviour or have I missed something?
SOLVED
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = 1";
Is the only thing I think is wrong... What do you get with :
Select * from TestCampaign
have you set up any triggers based on this table name? After update, before update triggers may prevent you from storing the required data on the table.
Also, MySQL may use 0 as id value if you don't specify the value of the id at sending insert command. Are you sure the value of your id is 1 in the record you want to update? If you have run insert statements before on your table, the id may be a larger number than 1, because of the MySQL indices (I guess this may be the problem).
I don't know how exactly PHP statements are processed when sending them to MySQL, but I would recommend you to use PDO statements, the PHP syntax would look something like this:
$sql = $pdo->prepare("UPDATE TestCampaign SET Campaign = ? WHERE id = ?");
$sql->bindParam(1, $Test);
$sql->bindParam(2, 1);
$sql->execute();
Tutorial: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
I would also echo your $Test variable to check what is stored in it.
Hope it helps...
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.

MySQL ROLLBACK not actually rolling back

I have the following PHP code:
$dbh->beginTransaction();
$dbh->exec("LOCK TABLES
`reservations` WRITE, `settings` WRITE");
$dbh->exec("CREATE TEMPORARY TABLE
temp_reservations
SELECT * FROM reservations");
$dbh->exec("ALTER TABLE
`temp_reservations`
ADD INDEX ( conf_num ) ; ");
// [...Other stuff here with temp_reservations...]
$dbh->exec("DELETE QUICK FROM `reservations`");
$dbh->exec("OPTIMIZE TABLE `reservations`");
$dbh->exec("INSERT INTO `reservations` SELECT * FROM temp_reservations");
var_dump(GlobalContainer::$dbh->inTransaction()); // true
$dbh->exec("UNLOCK TABLES");
$dbh->rollBack();
Transactions are working fine for regular updates/inserts but the above code for some reason is not. When an error happens above, I'm left with a completely empty reservations table. I read on the PDO::beginTransaction page that "some databases, including MySQL, automatically issue an implicit COMMIT when a database definition language (DDL) statement such as DROP TABLE or CREATE TABLE is issued within a transaction". The MySQL manual has a list of "Data Definition Statements", which I would assume is the same as DDL mentioned above which lists CREATE TABLE but I am only creating a temporary table. Is there any way around this?
Also, does the fact that I'm left with an empty reservations table show that a commit occurred after the DELETE QUICK FROM reservations query?
Edit: On an additional note, the INSERT INTO reservations line also produces the following error:
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.
I tried doing $dbh->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY , true); but this doesn't seem to affect it. I'm assuming it would have something to do with the transaction, but I'm not sure. Can anyone pinpoint what exactly is causing this error as well?
Your OPTIMIZE TABLE statement is causing an implicit commit.
I'm not sure exactly what you're trying to do, but it looks you can shorten your code to:
$dbh->exec("OPTIMIZE TABLE `reservations`");
All the other code is just making the job more complex, for no gain.
I'm also assuming you're using InnoDB tables, because MyISAM tables wouldn't support transactions anyway. Every DDL or DML operation on a MyISAM table implicitly commits immediately.
By the way, buffered queries have nothing to do with transactions. They have to do with fetching SELECT result sets one row at a time, versus fetching the whole result set into memory in PHP, then iterating through it. See explanation at: http://php.net/manual/en/mysqlinfo.concepts.buffering.php

PHP MySQL Insert fail after DELETE

I got two tables. One is account, another is Interest.
One account can have multi Interests and It can be edited.
Now, the process is deleting all Interest of this account then insert these insterests.
The QUERY IS:
"DELETE FROM Interests WHERE account_id='$id'"
"INSERT INTO Interests (account_id, interest_name) VALUES('$id', '$name')"
I use the both query when user update their account, but the insert is fail, there is nothing insert into the table (ps. the interests_id is auto_increment and this was be counted) but there is nothing new in the table. When I comment out the delete query. The insert will be successful.
Does any one know what can i do?
If you want to update your table records, you will do update operation.
like this:
UPDATE TABLE_NAME SET FIELD_NAME = 'VARIABLE_NAME'
WHERE PRIMERY_FIELD_NAME = 'VARIABLE_NAME' ;
you did not have to use these two queries, if you want to update data simply use the updat query of mysql.use this:
<?php
$query = "UPDATE Interests SET interest_name = '".$name."' WHERE account_id = '".$id."'" ;
mysql_query($query);
?>
If you want to update your table records then you may execute update operation. It like following
UPDATE Interests
SET
interest_name = '$name'
WHERE
accountno = '$id' ;
Try it. You may solve your problem by this way.
If you have queries failing, you should capture the error and see what went wrong. In all MySQL APIs for PHP, a query that fails returns a status code to indicate this. Examples of checking this status code are easy to find in the docs. But most developers fail to check the status.
Use transactions to ensure that both changes succeed together or neither are applied.
How to Decide to use Database Transactions
Definition of a transaction in MySQL: http://dev.mysql.com/doc/refman/5.5/en/glossary.html#glos_transaction
Syntax for starting and committing transactions in MySQL: http://dev.mysql.com/doc/refman/5.5/en/commit.html
You need to use InnoDB. MyISAM does not support transactions. http://dev.mysql.com/doc/refman/5.5/en/innodb-storage-engine.html
In PHP, you need to stop using the old ext/mysql API and start using MySQLi or PDO.
http://php.net/manual/en/mysqli.quickstart.transactions.php
http://php.net/manual/en/pdo.begintransaction.php
This happens because the query are treated as two single transaction, so the order of execution is not guaranteed.
The effect you are describing is because the insert is processed before delete, so the interests_id is auto-incremented properly, then the row is deleted by delete statement.
You should change the query logic or perform both queries in one single transaction.

Postgresql and PHP: is the currval a efficent way to retrieve the last row inserted id, in a multiuser application?

Im wondering if the way i use to retrieve the id of the last row inserted in a postgresql table is efficent..
It works, obviously, but referencing on the serial sequence currval value could be problematic when i have many users adding rows in the same table at the same time.
My actual way is:
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
pg_close($pgConnection);
Well, its just a test atm.
But anyway, i can see 3 issues with this way:
Referencing on the customer_id_seq, if two user do the same thing in the same time, could happen that them both get the same id from that way... or not?
I have to know the table's sequence name. Becose pg_get_serial_sequence dont works for me (im newbie on postgresql, probably is a configuration issue)
Any suggestion/better ways?
p.s: i can't use the PDO, becose seem lack a bit with the transaction savepoint; I wont use zend and, in the end, i'll prefer to use the php pg_* functions (maybe i'll build up my classes in the end)
EDIT:
#SpliFF(thet deleted his answer): this would works better?
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
pg_query("BEGIN");
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
//do somethings with the new customer id
pg_query("COMMIT");
pg_close($pgConnection);
If you use a newer version of PostgreSQL (> 8.1) you should use the RETURNING clause of INSERT (and UPDATE) command.
OTOH if you insist on using one of the sequence manipulation functions, please read the fine manual. A pointer: "Notice that because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did."
Insert and check curval(seq) inside one transaction. Before commiting transaction you'll see curval(seq) for your query and no matter who else inserted at the same time.
Don't remember the syntax exactly - read in manual (last used pgsql about 3 years ago), but in common it looks like this:
BEGIN TRANSACTION;
INSERT ...;
SELECT curval(seq);
COMMIT;
ex. minsert into log (desc,user_id) values ('drop her mind',6) returning id

Categories