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.
Related
Ive just started learning PDO and I'm struggling by simply inserting a new record based from
$lastid = $db->lastInsertId();
The ID gets created in the database table from another function.
But nothing happens when i try to insert a new record based on that ID.
function add_name($last_id, $name) {
$db = some_db();
$query = "INSERT INTO team (name) VALUES (:name) WHERE id = '".$last_id."'";
$stmt = $db->prepare($query);
$stmt ->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->execute();
}
INSERT ... WHERE is not valid SQL. If you are inserting a new record, an autoincremnt ID will be generated at that time (if you have such defined for the table).
If you are trying to INSERT a new row into a related table with the last id from another table, then you would set that value as one of your column inputs. So the workflow would look like this:
INSERT [column data for table_a] INTO table_a
[GET autoincrement from last insert]
INSERT (table_a_foreign_key_column, [other table_b columns]) VALUES (table_a_id, [other table_b values) INTO table_b
UPDATE:
Since UPDATE is what you want, you can make update like this:
UPDATE team
SET name = :name
WHERE id = :id
You should use parameters for both name and id values. It is still not clear to me why you would need to make an insert and then an update within the same script execution. It's not like you received any more input from the user that you did not already have. I would guess you could just insert this name values when first creating the record and save yourself the extra trouble of multiple queries.
i think your sql query is wrong, try this:
function add_name($last_id, $name) {
$db = some_db();
$query = 'INSERT INTO team (id, name) VALUES (:id, :name)';
$stmt = $db->prepare($query);
$stmt ->bindParam(':name', $name, PDO::PARAM_STR);
$stmt ->bindParam(':id', $last_id, PDO::PARAM_INT);
$stmt->execute();
}
MySQL Insert Where query
I have a web program which allows the administrator to update a user's information... With that being said, I only want columns updated which have indeed been 'updated'...
I have done quite a bit of researching on this and it seems that all methods use outdated querys, which do not make use of the prepare statement to escape input...
Can someone please help me with the statement?
Essentially in psuedocode:
Update FIRSTNAME if $editedUserdata['firstname'] != FIRSTNAME, LASTNAME if $editedUserData['lastname'] != LASTNAME ...etc...
Here is what I have for the post code...
$password = sha1($password);
$editedUserData = array(
'firstname' => $firstname,
'lastname' => $lastname,
'username' => $username,
'password' => $password,
'cellphone' => $cellphone,
'security_level' => $seclvl,
'email' => $email,
'direct_phone' => $direct,
'ext_num' => $extension,
'is_active' => $userflag
);
Then it should be something like
$query = $this->db->prepare('UPDATE FIRSTNAME if(?) IS NOT FIRSTNAME, LASTNAME if(?) IS NOT LASTNAME, USERNAME if (?) IS NOT USERNAME.... VALUES (:firstname, :lastname, :username).....'
if ($query -> execute($editedUserData)) {
more code....
According to MySQL documentation -
Ref: (http://dev.mysql.com/doc/refman/5.0/en/update.html)
"If you set a column to the value it currently has,
MySQL notices this and does not update it."
Maybe I'm not understanding the problem which you're trying to solve but you don't have to test if field value did change.
If field value is "A" and you put there an "A" it will remain the same otherwise, if you put there a "B" it will be updated as expected
The prepared statement would be something like
$stmt = $dbh->prepare("
UPDATE table_name
SET
field1 = :value1,
field2 = :value2
WHERE
field0 = :key
");
$stmt->bindParam(':value1', $value1, PDO::PARAM_STR);
$stmt->bindParam(':value2', $value2, PDO::PARAM_STR);
$stmt->bindParam(':key', $key, PDO::PARAM_INT);
$stmt->execute()
Run a single statement to update the row.
Firstly, what's the unique identifier for a row in the users table, is there a unique userid or username? You'll want a WHERE clause on the UPDATE statement so that only that row will be updated.
The normative pattern for an UPDATE statement to update several columns in a single row is like this:
UPDATE users
SET col2 = 'value'
, col3 = 'another value'
, col4 = 'fi'
WHERE idcol = idvalue ;
To use a prepared statement with PDO, the SQL text could look something like this, if you use named placeholders:
UPDATE users
SET col2 = :col2_value
, col3 = :col3_value
, col4 = :col4_value
WHERE idcol = :id_value
Or this, if you use positional notation for the placeholders:
UPDATE users
SET col2 = ?
, col3 = ?
, col4 = ?
WHERE idcol = ?
(My personal preference is to use the named placeholders, rather than positional, but either will work.)
This is how I'd do it, run the prepare, then the bind_param, and then the execute.
$sql = "UPDATE users
SET col2 = :col2_value
, col3 = :col3_value
, col4 = :col4_value
WHERE idcol = :id_value ";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':col2_value', $col2_val, PDO::PARAM_STR);
$stmt->bindParam(':col3_value', $col3_val, PDO::PARAM_STR);
$stmt->bindParam(':col4_value', $col4_val, PDO::PARAM_STR);
$stmt->bindParam(':id_value' , $id_val, PDO::PARAM_STR);
$stmt->execute();
To do something different, to dynamically create the SQL text, and adjust the bindParam calls, that would add unnecessary complexity to the code. There's no performance advantage to doing that; when that UPDATE statement runs, MySQL has to lock the row, store a new copy of the row. It doesn't really save anything (aside from a few bytes of data transfer) to avoid sending a column value that hasn't changed.
If you realy want to use cases, read this.
There is no reason to do it in your case, as stated from #spencer7593 in the comments:
That's WAY more overhead... roundtrips to the database, parsing the
statement, developing an execution plan, executing the statement,
obtaining locks, returning a status, client checking the status, etc.
That's just seems an all-around inefficient approach.
I assume that any RDBMS is smart enough, to notice, that Caches etc should not be recalculated (if nothing changes), if that is the problem.
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.!
I have a PHP function which inserts multiple records into MySQL:
function commit_purchase($asset_type_ID, $org_ID, $asset_desc, $asset_cost, $date, $org_to_member_ID, $asset_ID, $purchaser_cur_invest, $purchaser_cred_deb, $purchaser_balance) {
global $db;
$query = "START TRANSACTION;
INSERT INTO assets
(asset_type_ID, org_ID, asset_desc, asset_cost, asset_value, purchase_date, is_approved)
VALUES
(:asset_type_ID, :org_ID, :asset_desc, :asset_cost, :asset_cost, :date, 1);
SET #asset_ID = LAST_INSERT_ID();
INSERT INTO cash_out
(org_to_member_ID, amount, description, date, is_approved, asset_ID)
VALUES
(:org_to_member_ID, :asset_cost, :asset_desc, :date, 1, #asset_ID);
SET #cash_out_ID = LAST_INSERT_ID();
INSERT INTO shares
(asset_ID, member_ID, percent_owner, is_approved)
SELECT assets.asset_ID, pending_asset_shares.member_ID, pending_asset_shares.percent_owner, pending_asset_shares.is_approved
FROM assets, pending_asset_shares
WHERE assets.asset_ID = #asset_ID;
DELETE FROM pending_asset_shares
WHERE asset_ID = :asset_ID;
DELETE FROM pending_assets
WHERE pending_asset_ID = :asset_ID;
INSERT INTO trans_log
(translog_id, trans_type, org_to_member_ID, date, purchaser, asset_ID, cur_invest, cash_out_ID, cred_deb, balance)
VALUES
(DEFAULT, 3, :org_to_member_ID, :date, :org_to_member_ID, #asset_ID, :purchaser_cur_invest, #cash_out_ID, :purchaser_cred_deb, :purchaser_balance);
COMMIT;";
$statement = $db->prepare($query);
$statement->bindValue(':asset_type_ID', $asset_type_ID);
$statement->bindValue(':org_ID', $org_ID);
$statement->bindValue(':asset_desc', $asset_desc);
$statement->bindValue(':asset_cost', $asset_cost);
$statement->bindValue(':date', $date);
$statement->bindValue(':org_to_member_ID', $org_to_member_ID);
$statement->bindValue(':purchaser_cur_invest', $purchaser_cur_invest);
$statement->bindValue(':purchaser_cred_deb', $purchaser_cred_deb);
$statement->bindValue(':purchaser_balance', $purchaser_balance);
$statement->bindValue(':asset_ID', $asset_ID);
$statement->execute();
$statement->closeCursor();
return $asset_ID;
I am trying to use the first INSERT statment's LAST_INSERT_ID (#asset) as a variable for my next function. The way I am calling the above function, in hopes of setting the variable, is:
$asset_ID = commit_purchase($asset_type_ID, $org_ID,.......etc.)
I am pretty sure my problem is somewhere around the "return $asset_ID" in my SQL statement. I have been able to do this successfully when using only 1 LAST_INSERT_ID call.
Nothing is being returned at all.
Ok, as mentioned in my comments, you can use beginTransaction to break this up. http://php.net/manual/en/pdo.begintransaction.php
Once you have done that, it's just a matter of getting the last inserted ID. You can use lastInsertId for that: http://php.net/manual/en/pdo.lastinsertid.php
Breaking this down into multiple queries would really be the best solution, but to answer your original question: If you want to get the value of MySQL variables in PHP, just execute a SELECT query:
$asset_ID = mysql_result( mysql_query( 'SELECT #asset_ID' ) );
I'm new to php. So, please forgive me if this seems like a dumb question.
Say i have a MySQL insert statement insert into table (a,b) values (1,2),(3,4),(5,6). table 'table' has a auto increment field called 'id'.
how can I retrieve all the ids created by the insert statement above?
It will be great if i get an example that uses mysqli.
You can't. I would suggest that you maintain your own ids (using guid or your own auto-increment table) and use it when you insert into the table.
But it's possible to get the auto-increment value for the last inserted using LAST_INSERT_ID():
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
AngeDeLaMort's answer is almost right. Certainly, the most appropriate way to deal with the problem is to insert one row at a time and poll the insert_id or generate the sequence elsewhere (which has additional benefits in terms of scalability).
I'd advise strongly against trying to determine the last insert_id and comparing this the most recent insert_id after the insert - there's just too may ways this will fail.
But...an alternative approach would be:
....
"INSERT INTO destn (id, data, other, trans_ref)
SELECT id, data, other, connection_id() FROM source";
....
"SELECT id FROM destn WHERE trans_ref=connection_id()";
....
"UPDATE destn SET trans_ref=NULL where trans_ref=connection_id()";
The second query will return the ids generated (note that this assumes that you use the same connection for all 3 queries). The third query is necessary because connection ids to go back into the pool when you disconnect (i.e. are reused).
C.
In some cases, if you have another identifier of sort such as a UserID, you could filter your query by UniqueID's greater than or equal to mysql_insert_id(), limit by the number of affected rows and only display those by the user. This would really only work inside of a transaction.
$SQL = "INSERT INTO Table
(UserID, Data)
VALUES
(1,'Foo'),
(1,'Bar'),
(1,'FooBar')";
$Result = mysql_query($SQL);
$LastID = mysql_insert_id();
$RowsAffected = mysql_affected_rows();
$IDSQL = "SELECT RecordID
FROM Table
WHERE UserID = 1
AND RecordID >= '$LastID'
LIMIT '$RowsAffected'";
$IDResult = mysql_query($IDSQL);
as a follow up to AngeDeLaMort:
You could seperate your inserts and do it something like this:
$data = array (
array(1,2),
array(3,4),
array(5,6)
);
$ids = array();
foreach ($data as $item) {
$sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
mysql_query ($sql);
$id[] = mysql_insert_id();
}
Now all your new id's are in the $id array.
Maybe I can do this
$insert = "insert into table (a,b) values (1,2),(3,4),(5,6)";
$mysqli->query($insert);
$rows_to_be_inserted=3;
$inserted_id = $mysqli->insert_id // gives me the id of the first row in my list
$last_row_id = ($inserted_id+$rows_to_be_inserted)-1;
$mysql->query("select * from table where id between $inserted_id and $last_row_id");
what to you guys say?