I am trying to insert a number of ids into a new table. The list of ids is taken from another table.
My Code:
$stmt = $con->prepare('DROP TABLE tblname;
CREATE TABLE tblname (
id BIGINT
);
INSERT INTO tblname (id)
SELECT tablename2.colname
FROM tablename2
WHERE (col1 = "value" AND col2 = "value")');
$stmt->execute();
I create and dump the table because its part of an update script.
(Is there a better way to do that than dump/create?)
The script needs the current list of ids and I am trying to get create a table with those ids. What happens is, whenever I run the code (using putty) it returns "0" and the table remains empty.
What did I do wrong?
Any general help/advice concerning php/mysql welcome too!
First, make sure PDO is set to throw exceptions if a query fails:
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Then, perhaps catch the exception (or let the exception halt the application) and see what is wrong.
I do believe your insert query is, erm, off:
INSERT INTO tblname (id)
SELECT tblname2.colname
FROM tablename2
WHERE col1 = "val"
Just seems ambiguous, and messy, even more: it seems unsafe. However, try this -equally messy- query:
INSERT INTO tblname (id) VALUES (
SELECT colname
FROM tblname2
WHERE col1 = "val"
);
Last but not least, make sure you're running PHP version 5.3+, because prior to that version, PDO did not support multiple queries.
My suggestion, though, is not to use multiple queries for the INSERT query. Instead, I'd use a transaction and separate the select and insert query. I'd also add a safety-net to the DROP TABLE and CREATE TABLE queries, too:
try
{
$con->beginTransaction();//DROP & CREATE:
if ($con->exec('DROP TABLE IF EXISTS tblname') === false)
{//query wasn't executed
$con->rollback();
exit($con->errInfo());//error
}
if ($con->exec('CREATE TABLE IF NOT EXISTS tblname(...);') === false)
{
$con->rollback();
exit($con->errInfo());
}
$con->commit();//alter tables.
$con->beginTransaction();//INSERT TRANSACTION
$stmt = $con->prepare('INSERT INTO tblname (id) VALUES (:id)');
$bind = array(
':id' => null
);
$select = $con->prepare(
'SELECT colname FROM tblname2 WHERE col1 = :val1 AND col2 = :val2'
);
$select->execute(
array(
':val1' => 'value1',
':val2' => 'value2'
)
);
while ($row = $select->fetch(PDO::FETCH_ASSOC))
{
$bind[':id'] = $row['colname'];
$stmt->execute($bind);//inserts row
$stmt->closeCursor();//optional
}
$con->commit();//save changes to db
}
catch (PDOException $e)
{
//rollback transaction
$con->rollback();
exit($e->getMessage());//show what went wrong, and exit.
}
You are missing a keyword here to INSERT the value into the table, which is VALUES.
The correct syntax will be
INSERT INTO tblname (id) VALUES
SELECT tablename2.colname
FROM tablename2
WHERE (col1 = 'value' AND col2 = 'value')
The values should be into SINGLE QUOTES, tried and test myself and these 2 work for me every time.!
Related
I am trying to create a query inside a PDO script that checks if a record exists if it does the query should update the record and if it doesn't exist it should create a new one.
The column that should only exist once in the table is not an INDEX key (cannot make it unique right now) so it is not set as unique and I cannot use the ON DUPLICATE KEY UPDATE
I would like to use this queries logic below to make it work:
$stmt = $conn->prepare('IF EXISTS (SELECT * FROM `Table1` WHERE `code`= :code )
UPDATE `Table1`
SET `code_stat` = 2
WHERE code = :code
ELSE
INSERT INTO `Table1` (`code`,`code_stat`)
VALUES (:code, 2 ) ' );
$stmt->execute([
'code' => $_POST['code']
]);
The problem is when executing the query I get the following error saying there is a syntax problem:
SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near
'IF EXISTS (SELECT * FROM Table1 WHERE code= ? ) UPDATE Table1' at line 1
If you can't add a unique key to the table, you can attempt an update first, and if that doesn't update any rows, do an insert. Something like this:
$stmt = $conn->prepare('UPDATE `Table1` SET `code_stat` = 2 WHERE code = :code');
$stmt->execute(array(':code' => $_POST['code']));
if (!$stmt->rowCount()) {
// no rows updated, so insert
$stmt = $conn->prepare('INSERT INTO `Table1` (`code_stat`, `code`) VALUES (2, :code)');
$stmt->execute(array(':code' => $_POST['code']));
}
Note that you may need to set the PDO::MYSQL_ATTR_FOUND_ROWS attribute to ensure that the UPDATE query returns 1 if it finds the row but the value doesn't change. You must set that attribute when you make the connection e.g.
$conn = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_FOUND_ROWS => true));
Why not write a stored procedure to handle this, similar to the below:
DROP PROCEDURE IF EXISTS db.SP_NEW_CODE;
CREATE PROCEDURE db.`SP_NEW_CODE`(IN `in_code` INT)
BEGIN
DECLARE numFound INT DEFAULT 0;
SET numFound=(SELECT * FROM `Table1` WHERE `code`= in_code);
IF (numFound=0) THEN
INSERT INTO `Table1` (`code`,`code_stat`) VALUES (in_code, 2 );
ELSE
UPDATE `Table1` SET `code_stat` = 2 WHERE code = in_code
END IF;
END;
From your code, simple execute CALL SP_NEWCODE(3); (for example, where 3 is the appropriate code value).
I have two queries and I want to combine them into one so that it only returns one row in my database.
I have tried UNION but I keep getting an error. Can anyone please advise me on the code for it?
Below are my queries:
if(isset($_POST["response"]))
{
$query = "INSERT INTO response(response) VALUES (:response)";
$statement = $conn->prepare($query);
$statement->execute(
array(
':response' => $_POST["response"]
)
);
$query = " INSERT INTO response (student_id)
SELECT studentid
FROM student
WHERE studentid = '".$_SESSION['studentid']."'";
$statement = $conn->prepare($query);
$statement->execute(
);
UNION is used for combining multiple SELECT queries into a single result set. Check the mySQL (or any generic ANSI SQL) documentation.
Anyway, for no apparent reason you are making two INSERT queries when it looks like you're inserting into the same table and presumably want to insert everything into the same row in the same table. Right now you will make 2 rows instead of 1. You can insert more than one field as part of a single query.
I'm thinking:
if(isset($_POST["response"]))
{
$query = "INSERT INTO response (student_id, response) SELECT studentid, :response FROM student WHERE studentid = :studentID";
$statement = $conn->prepare($query);
$statement->execute(
array(
':response' => $_POST["response"],
':studentID' => $_SESSION['studentid']
)
);
}
However, since you only require the studentID in the table, and you already have the studentID from the session, it seems pointless to select from the students table at all. The only exception might be if you need to verify that the value in the session is correct - but surely you have already verified it before you added it to the session? If you haven't, you certainly should.
So in fact simply
if(isset($_POST["response"]))
{
$query = "INSERT INTO response (student_id, response) VALUES (:studentID, :response)";
$statement = $conn->prepare($query);
$statement->execute(
array(
':response' => $_POST["response"],
':studentID' => $_SESSION['studentid']
)
);
}
should be sufficient.
I'm having the following query, it contains a Temporary Table. If I use a Temporary Table, it returns an EMPTY ARRAY. If I removed the Temporary Table it returns an appropriate records.
The following SQL Query contains a simple query, I just created a Temporary Table and inserted some records and I'm doing SELECT Query in that Temporary Table. I executed the same code in phpMyAdmin, it returns an appropriate records, but in PDO returns an EMPTY ARRAY.
Sample and Simple SQL Query:
Case #1: With Temporary Table - Returns an EMPTY ARRAY
<?php
$query = <<<SQL
CREATE TEMPORARY TABLE TempContact (
ContactId int,
FirstName varchar(30),
LastName varchar(30),
IsActiveContact Boolean
);
INSERT INTO TempContact (ContactId, FirstName, LastName, IsActiveContact)
SELECT CT.ContactId, CT.FirstName, CT.LastName,
CASE WHEN SL.SalesId IS NOT NULL THEN TRUE ELSE FALSE END AS IsActiveContact
FROM Contact CT
LEFT JOIN Sales SL ON CT.ContactId = SL.ContactId;
SELECT TC.* FROM TempContact TC;
SQL;
$stmt = $db->prepare($query);
$result = $stmt->execute() ? $stmt->fetchAll() : null;
?>
Case #2: Without Temporary Table - Returns an appropriate records
<?php
$query = <<<SQL
SELECT CT.ContactId, CT.FirstName, CT.LastName,
CASE WHEN SL.SalesId IS NOT NULL THEN TRUE ELSE FALSE END AS IsActiveContact
FROM Contact CT
LEFT JOIN Sales SL ON CT.ContactId = SL.ContactId;
SQL;
$stmt = $db->prepare($query);
$result = $stmt->execute() ? $stmt->fetchAll() : null;
?>
My actual code is so complex, due to easy understanding I added this simple query.
I also checked for any error in my Query (Case #1 Query) using print_r($stmt->errorInfo());, but it returns an EMPTY ARRAY (i.e., No Error in my Query);. Moreover its not throwing any PDOException.
Kindly assist me, how to get the records from the Temporary Table SELECT
With PDO you're supposed to execute one query at a time. It's not like the SQL console where you can push in a bunch of statements at once.
You're expected to check that each query completed successfully before moving on to the next one. If you split this up into several prepare/execute pairs it will work as-is. The reason the second succeeds is because it consists of a single statement.
PHP PDO fetchAll() returns empty array while SELECTing Temporary Table
Obviously, it is not true. Anyone can run the following code utilizing a temporary table and see the result
$pdo->query("CREATE temporary TABLE tmptest (id int auto_increment primary key, name varchar(255))");
$stmt = $pdo->prepare("INSERT INTO tmptest VALUES (NULL, ?)");
foreach (['Sam','Bob','Joe'] as $name)
{
$stmt->execute([$name]);
}
$stmt = $pdo->prepare("SELECT * FROM tmptest");
$stmt->execute();
var_export($stmt->fetchAll(PDO::FETCH_KEY_PAIR));
which outputs the expected
array (
1 => 'Sam',
2 => 'Bob',
3 => 'Joe',
)
While your problem is coming from the fact that you are running multiple queries in a single call and so the first fetchAll() is naturally returns an empty result as the first query returns nothing. To get your data you should be either run your queries in separate statements or move the internal pointer to the next result and then call for fetchAll():
$pdo->query("CREATE temporary TABLE tmptest (id int auto_increment primary key, name varchar(255))");
$pdo->query("CREATE temporary TABLE tmptest2 (id int auto_increment primary key, name varchar(255))");
$stmt = $pdo->prepare("INSERT INTO tmptest VALUES (NULL, ?)");
foreach (['Sam','Bob','Joe'] as $name)
{
$stmt->execute([$name]);
}
$stmt = $pdo->prepare("INSERT INTO tmptest2 SELECT * from tmptest;SELECT * FROM tmptest2");
$stmt->execute();
$stmt->nextRowset();
var_export($stmt->fetchAll(PDO::FETCH_KEY_PAIR));
I don't know how to update or insert multiple rows by using PDO. Please help me.
Something that is in my mind is:
$stmt = $dbh->query("update_line_1; update_line_2; update_line_3");
//update_line_1: update table a set a.column1 = "s1" where a.id = 1
//update_line_2: update table a set a.column1 = "s2" where a.id = 2
//....
$stm = $dbh->query("insert_line_1; insert_line_3; insert_line_3");
//something is like the update line above.
I don't know this way works or not. And If you have another way, please let me know. Thank you so so much.
And if I use prepare statement, I just update each row each time. (This is much more safe than above)
$stmt = $dbh->prepare("update table a set a.colum1 = :column1 where a.id = :id");
$stmt->bindParam(":column1","s1");
$stmt->bindparam(":id",1);
$stmt->execute();
The most hate thing I don't want to do is using a loop goes through all elements in an array, and update or insert each element each time
Is another way to mass safely update or insert multiple rows to database? thank for your help.
Sorry about my English.
For inserts, you can insert multiple rows worth of data with the following syntax:
INSERT INTO table (col1, col2, col3)
VALUES
('1', '2', '3'),
('a', 'b', 'c'),
('foo', 'bar', 'baz')
For updates, the update will by default effect as many rows as meet the criteria of the query. So something like this would update an entire table
UPDATE table SET col = 'a'
If you are trying to update different values for each row, you don't really have much of a choice other than to do a query for each operation. I would suggest however that, building on your PDO example, you could do something like this:
$update_array = array(
1 => 'foo',
2 => 'bar',
10 => 'baz'
); // key is row id, value is value to be updated
$stmt = $dbh->prepare("UPDATE table SET column1 = :column1 where id = :id");
$stmt->bindParam(":column1",$column_value);
$stmt->bindparam(":id",$id);
foreach($update_array as $k => $v) {
$id = $k
$column_value = $v;
$stmt->execute();
// add error handling here
}
With this approach you are at least leveraging the use of the prepared statement to minimize query overhead.
when updating a database having 4 tables, if a particular table hasn't got the data which is updating..then how can I insert the same to that table??
my database is based on SEO so inserting web information to all 4 tables. these tables indexed by domain name. so if four tables got domain name which is updating then it will update all table otherwise it wont. but I want add that domain and info to table which does not have the same info.
right now I am using normal update query
mysql_query("UPDATE LOW_PRIORITY dscrpn SET descr='$descr',title='$title' WHERE web='".mysql_real_escape_string($urweb)."'");
You can't (as far as I know) write one single statement that will either update the existing row, or insert a new one if it doesn't exist.
What you can do is send an update, then check the number of rows affected by the update (mysql_affected_rows); if it had zero rows affected, then do an insert. You could do this all in MySQL, but I'd probably just do it in the PHP code.
see http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html
self-contained example (using PDO):
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
setup($pdo);
$stmt = $pdo->prepare('
INSERT INTO
so_dscrpn
(web,descr,title)
VALUES
(?,?,?)
ON DUPLICATE KEY UPDATE
descr=VALUES(descr),
title=VALUES(title)
');
$data = array(
array('uri1', 'desc1', 'title1'),
array('uri2', 'desc2', 'title2'),
array('uri1', 'desc3', 'title3')
);
foreach($data as $row ) {
$stmt->execute($row);
}
foreach( $pdo->query('SELECT * FROM so_dscrpn', PDO::FETCH_ASSOC) as $row ) {
echo join(', ', $row), "\n";
}
function setup($pdo) {
$pdo->exec('
CREATE TEMPORARY TABLE so_dscrpn (
web varchar(48) NOT NULL,
descr varchar(48),
title varchar(48),
unique key(web)
)
');
}
prints
uri1, desc3, title3
uri2, desc2, title2