I'm a beginner with PDO and MySQL, so here's my question :
How can I be sure that when performing an INSERT .. SELECT (or MULTIPLE INSERT)
all data will be inserted in database?
I know there is a rowCount() function but the number of rows inserted is dynamic.
The only way I see would be to make a SELECT count(*), and then compare it with the rowCount(), but I'm not sure I'm doing it the right way.
And if not all data were inserted, is it possible to get rows which didn't work?
Also, is it possible that a SELECT query fails and retrieves only a few part of the data? (ex : It must retrieve 1000 rows but due to some failure, it retrieves 700) Or it's all or nothing?
Thanks for the help.
How can I be sure that when performing an INSERT .. SELECT (or MULTIPLE INSERT) all data will be inserted in database?
You should tell PDO to throw an exception in case of error and thus there will be a PHP error in case of a failed query.
I know there is a rowCount() function
Row count has nothing to do in your case.
And if not all data were inserted, is it possible to get rows which didn't work?
It is advised to redo all the successful yet queries instead. To do so you have to wrap your inserts in a transaction.
However, if you want to keep alll the previous inserts in place, you may wrap execute call in a try and catch operator and do whatever workaround inside.
Also, is it possible that a SELECT query fails and retrieves only a few part of the data?
No.
Related
I'm trying to refine my database access classes to help at the time of processing form data. What I'm trying to accomplish is this:
add an SQL query to my connection object.
classify the SQL query by its commands and arguments.
use the classification data to automatically add the required attribute to a given form input tag (and, optionally, insert a given or corresponding RegEx for advanced matching).
add a session-driven temporary object holding the form members to check for both completeness and compliancy with a given set of rules or matches.
execute the SQL query once all the given requirements are satisfied.
Then, the way to proceed (in my actual code) is like this:
if (!empty($data = \Helpers\Forms\getData($_POST))) {
if (!empty($rules = \Helpers\Forms\getRules($_POST))) {
if ($data->isCompliant($rules)) {
// rest continues here...
}
}
}
So far, I've got steps 1, 3 and 5 fully completed. I got steps 2 and 4 just partially implemented because I need a way to do a metadata scan on a given prepared SQL query and that's where I'm a bit lost.
According to the PDO manual, the columnCount() method doesn't provide an accurate result until the execute() method is called.
However, the execute method actually executes the query and I don't want to do it because if it's a SELECT query, it would actually be ok but not for a INSERT, DELETE, UPDATE or any other kind of query.
So my question is... is there any way to get the column count for a given SQL query without executing it? Or maybe... is there a way to perform a dummy execution of a given SQL query to obtain this column count value?
Until recently I've been using mysql_real_escape_string() to fix most of my variables before making SQL queries to my database. A friend said that I should be using PDO's prepared statements instead, so after reading a bit about them I'm now switching over to them.
I've only encountered one problem so far in switching over, and that's counting the rows to returned by a SELECT statement. On occasion in my code, I'd run an SQL query and then count the number of rows returned from the SELECT statement. Depending on whether a result set returned, I would take different actions. Sometimes I do need to use the result set from it. MySQL let me go straight to mysql_fetch_assoc() after mysql_num_rows() with no problem. However, PDO doesn't seem to have anything like mysql_num_rows().
I've been reading some responses on SO that gave me a solution, to either use COUNT() in the SQL statement or to use the PHP function count() on the result set. COUNT() would work fine in the SQL statement if I didn't need the result set in some places, however, several people have mentioned that using count() on the result set is fairly inefficient.
So my question is, how should I be doing this if I need to count the number of rows selected (if any), then run a script with the result set? Is using count() on the result set the only way in this case, or is there a more efficient way to do things?
Below is a short example of something similar to my previous SQL code:
$query=mysql_query('SELECT ID FROM Table WHERE Name='Paul' LIMIT 1);
if(mysql_num_rows($query)>0)
{
print_r(mysql_fetch_assoc($query));
}
else
{
//Other code.
}
Thanks.
EDIT
I do know that you use fetchAll() on the statement before counting the result set (which gives me what I need), but I'm just trying to figure out the most efficient way to do things.
$stmt->rowCount();
http://php.net/manual/en/pdostatement.rowcount.php
the rows must be fetched(buffered into memory, or iterated) for it to work. It's not uncommon for your pdo driver to be configured to do this automatically.
You will have to use Count(). You can run two queries like
SELECT COUNT(ID) FROM Table WHERE Name='Paul'
one you have get the count, then run the query with select clause
SELECT ID FROM Table WHERE Name='Paul' LIMIT 1
Count() function is not inefficient at all if you are using it like COUNT(ID), because most probably id is primary key and have an index. MYSQL wont even have to access the table.
In php, I'm trying to insert a value into one table, return an auto-incremented value, and then insert that value along with other values into a second table.
I'm running into a few problems. First, while there's a lot of ways of doing this in SQL, I have to do this with php's mysql functions. I'm afraid of weird errors if I combine multiple statements together. Second, like I mentioned, I need this to be done in one query, as it'll be used for a web application.
My current query is like this
INSERT INTO TABLE1 VALUES(*);
INSERT INTO TABLE2
SELECT max(AutoIncrementedColumn)
FROM TABLE1;
The problem I'm having is that mysql_query() doesn't support multi queries. Also, I believe mysql_escape_string() removes anything it believes to be a multi query, so even if I could somehow get mysql_query to believe my query is not a multi query, I'm still out of luck unless I write my own escape method.
Does anyone have any ideas on how to deal with this problem?
EDIT: Forgot to mention that I can't use mysql_insert_id because the column that's autoincrementing is of type Bigint.
I have a PHP foreach loop and a mysql insert statement inside of it. The loop inserts data into my database. I've never ran into this issue before but what I think is happening is that the insert dies (I do not have an "or die" statement after the insert) when it reaches a duplicate record. Even though there may be duplicate records in the table, I need this to just continue. Is there something that I need to specify to do this?
I'm transferring some records from one table to another. Right now, I have 20 records in table #1 and only 17 in table #2. I'm missing 3 records but only one of those are duplicated which violates the constraint on the table. The other two records should have been added. Can someone give me some advice here?
What's happening is that PHP is throwing a warning when the mysql insert fails and stopping on that warning. The best way to accomplish your goal is:
Create a custom exception handler
Set PHP to use the exception handler for warnings.
Wrap the insert attempt into a try / catch
When you catch the exception / warning, either log or output the mysql error but continue script execution.
This will allow your script to continue without stopping while at the same time explaining to you the problem.
One way around this would be to simply query the database for the record that you're about to insert. This way, your series of queries will not die when attempting to insert a duplicate record.
A slightly more efficient solution would be to query for [i]all[/i] of the records you're about to insert in one query, remove all the duplicates, then insert the new ones.
Do you insert multiple rows with one INSERT statement?
INSERT INTO xyz (x,y,z) VALUES
(1,2,3),
(2,3,5),
(3,4,5),
(4,5,6)
Then you might want to consider prepared statements
...or adding the IGNORE keyword to your INSERT statement
INSERT IGNORE INTO xyz (x,y,z) VALUES
(1,2,3),
(2,3,5),
(3,4,5),
(4,5,6)
http://dev.mysql.com/doc/refman/5.0/en/insert.html says:
If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead
You can still fetch the warnings but the insertion will not be aborted.
Not a good way cause you should figure out whats wrong, but to just prevent it from dieing try adding # in front of the function
#mysql_query = ...
INSERT INTO FOO
(ID, BAR)
VALUES(1,2),(3,4)
ON DUPLICATE KEY UPDATE BAR=VALUES(BAR)
I've recently started work on a new project using PHP5 and want to use their PDO classes for it. The problem is that the MySQL PDO Driver doesn't support rowCount() so there's no way to run a query and then get the number of affected rows, or rows returned, which is a pretty big issue as far as I'm concerned. I was wondering if anyone else has dealt with this before and what you've done to work around it. Having to do a fetch() or fetchAll() to check if any rows were affected or returned seems like a hack to me, I'd rather just do $stmt->numRows() or something similar.
You can issue a SELECT FOUND_ROWS() query right after the original SELECT query to get row count.
$pdo->query("SELECT * FROM users");
$foundRows = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
See also: MySQL Docs on FOUND_ROWS()
For those of you who are using MySQL stored procedures, this solution isn't really feasible. What I would suggest that you do is have your stored procedure create two rowsets. The first one will contain one row and one column, containing the number of records. The second will be the recordset you will use for fetching that number of rows.
The number of unlimited rows can be a SELECT COUNT(*) with the exact same WHERE clause as the second rowset without the LIMIT/OFFSET clauses.
Another idea could be to create a temporary table. Use your SELECT statement to populate the temporary table. Then you can use SELECT COUNT(*) FROM tmpTable for your first rowset and SELECT * FROM tmpTable for your second.
This question is based on several false assumptions and one outdated statement.
First of all, do not confuse number of affected and selected rows. PDO supported the former even back in '09.
Speaking of number of rows returned by SELECT statement - you just don't need that number. The data you have is enough.
And yeah, nowadays rowCount() supports number of rows selected from mysql as well. But again - you don't need that number in an average web-application anyway.