PDO Mysql same query but insert to multiple users [duplicate] - mysql

This question already has answers here:
What is the best way to insert multiple rows in PHP PDO MYSQL?
(4 answers)
Closed last year.
I would like through pdo insert multiple (bulk) rows with same value, only diffent is the user_id
I'm passing a array with userIds but i have no idea how to bind them.
<?php
require_once("db.php");
$usersId = $jsonData["usersId"];
$text = $jsonData["text"];
// Try to fetch the user from the database
$query = "INSERT INTO posts (user_id, text) VALUES (:usersId, :text)";
$stmt = $db->prepare($query);
// Bind value
$stmt->bindValue(":userId", $userId);
$stmt->bindValue(":text", $text, PDO::PARAM_STR);
// Execute
$result = $stmt->execute();
?>
My Tables:
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255)
);
INSERT INTO users (name)
VALUES ("Gregor"),
("Liza"),
("Matt"),
("Bob");
CREATE TABLE posts(
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
text VARCHAR(255)
);

You need a loop:
require_once("db.php");
$text = $jsonData["text"];
// Try to fetch the user from the database
$query = "INSERT INTO posts (user_id, text) VALUES (:usersId, :text)";
$stmt = $db->prepare($query);
// Bind value
$stmt->bindParam(":userId", $userId);
$stmt->bindValue(":text", $text, PDO::PARAM_STR);
// Execute
foreach ($jsonData["usersId"] as $userId) {
$result = $stmt->execute();
}
Use bindParam() so it binds to a reference to the variable. That allows you to reassign the variable each time through the loop without re-binding.

Related

auto_increment not setting value for primary key?

I'm baffled, when I use the terminal (mysql) and insert into username,account_password columns, user_id AUTO_INCREMENTS just as it should.
my table:
CREATE TABLE users (
user_id int NOT NULL AUTO_INCREMENT,
user_type VARCHAR(20) NULL,
creation_date TIMESTAMP NOT NULL,
username VARCHAR(100) NOT NULL,
account_password VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
);
yet when I use this script:
use strict;
use warnings FATAL => 'all';# good for debugging, FATAL kills program so warnings are more identifiable
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser); # good for debugging, sends info to browser
use DBI;
use DBD::mysql;
use Digest::SHA qw(sha256);
print header, start_html;
my $fName = param('firstName');
my $lName = param('lastName');
my $compName = param('compName');
my $email = param('email');
my $pswrd = param('password');
my $cnfPswrd = param('confPassword');
my $encpswrd = "";
#check passwords match, if not display error, and exit script
if ($pswrd eq $cnfPswrd) {
$encpswrd = sha256($pswrd);
} else {
print "Passwords did not match! refresh form!";
exit;
}
#database credentials, to be changed accordingly
my $database = "intsystest";
my $host = "localhost";
my $user = "root";
my $pw = "password";
my $dsn = "dbi:mysql:$database:localhost:3306";
#connect to database
my $dbh = DBI->connect($dsn, $user, $pw,
{ RaiseError => 1 }) or die "unable to connect:$DBI::errstr\n"; # <- this line good for debugging
#create, prepare, execute query, disconnect from DB
my $personsQuery = "INSERT INTO persons (first_name, last_name) VALUES (?,?)";
my $compQuery = "INSERT INTO company (company_name) VALUES (?)";
my $usersQuery = "INSERT INTO users (username, account_password) VALUES (?,?)";
my $sth = $dbh->prepare($personsQuery);
$sth->execute($fName, $lName);
$sth = $dbh->prepare($compQuery);
$sth->execute($compName);
$sth = $dbh->prepare($usersQuery);
$sth->execute($email, $encpswrd);
$dbh -> disconnect;
# additional processing as needed ...
print end_html;
I get this error:
DBD::mysql::st execute failed: Field 'user_id' doesn't have a default value at /usr/lib/cgi-bin/compSignUpDBCGI.pl line 44.
I'm assuming it's likely something wrong with the handler. What am I missing??
If your persons table has a foreign key to the users table then you need insert the users record first, then get the id of the new users record and add that to the SQL to insert the persons record.
Something like this:
my $usersQuery = "INSERT INTO users (username, account_password) VALUES (?,?)";
$sth = $dbh->prepare($usersQuery);
$sth->execute($email, $encpswrd);
$sth = $dbh->prepare('SELECT user_id FROM users WHERE username = ?');
$sth->execute($email);
my $user_id = $sth->fetch->[0];
my $personsQuery = "INSERT INTO persons (user_id ,first_name, last_name) VALUES (?,?,?)";
$sth = $dbh->prepare($personsQuery);
$sth->execute($user_id, $fName, $lName);
This is an area where DBIx::Class will definitely make your life easier.

Insert Rows with using the result from a group of select best way to do it

I have an array of tags inserted in my database, and I need to insert them in another table with itemID and tagID.
The thing is that i don't have the tagID - instead I have a TagName with the name. I need to get the tagID so I can insert it afterward, but I'm wondering if this is possible to achieve in one single query.
I mean search for the name, then get its tagID and then insert it the array, or even inserting them one by one would work.
if I understood you, my ways is: create two tables first. If you know better way, please let me know.
Table Tag
id keyword
Table C_Tag
id tag_id user_id
Foreign key Tag(id) Reference C_Tag (tag_id)
<?php
$tag=$_POST['tag_name'] //get the tag name
$current_user=$_POST['users_id'];// get the current user id
include 'db_tag.php';
$stmt = $db->prepare("SELECT keyword, id FROM Tag WHERE keyword = :tag ");
$stmt->bindParam(':tag', $tag);
$stmt->execute();
$row_tag = $stmt->fetchALL(PDO::FETCH_ASSOC);
foreach ($row_tag as $row_tag){
}
//if the keyword exist, only update the C_Tag table
if ($row_tag['term'] == $tag){
$stmt = $db->prepare("SELECT t.id, t.keyword, ct.tag_id, ct.user_id FROM Tag t , C_Tag ct WHERE t.id=ct.tag_id ");
$stmt->bindValue(':current_id',$current_user);
$stmt->execute();
$row = $stmt->fetchALL(PDO::FETCH_ASSOC);
foreach ($row as $row){
}
$row_id=$row['id'];
$row_tag_id=$row['tag_id'];
$row_user_id=$row['user_id'];
if( $current_user == $row_user_id && $row_id == ! $row_tag_id ){
//make sure same user cannot enter duplicate keyword
$stmt = $db->prepare ("INSERT INTO C_Tag (user_id, tag_id)
SELECT :current_id, id
FROM tag
WHERE keyword=:keyword
");
$stmt->bindValue(':current_id',$current_user);
$stmt->bindValue(':keyword', $tag);
$stmt->execute();
}
} else {
//if the keyword is new, I will insert it into both table
}
?>
this appears to be the solution
How to copy a row and insert in same table with a autoincrement field in MySQL?
insert into zr1f4_k2_tags_xref (id, tagID, itemID) select NULL, tagID, #itemID from zr1f4_k2_tags where name=#tagName
but i cant make it work.
this are the tables
zr1f4_k2_tags
id int(11)
name varchar(255)
published smallint(6)
zr1f4_k2_tags_xref
id int(11)
tagID int(11)
itemID int(11)
I'm trying to insert the ID of the tag related to the tagname and item ID which ill add explicitly. and the id is autonumeric

using an ID before it is created sql?

Hi i have a question about mysql
this is my query:
$geboortedatum = $_POST['dag'].'-'.$_POST['maand'].'-'.$_POST['jaar'];
$geboortedatum1 = $_POST['dag1'].'-'.$_POST['maand1'].'-'.$_POST['jaar1'];
try{
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "
INSERT INTO clienten
(client_voornaam,
client_achternaam,
client_geboortedatum,
client_geslacht,
client_adres,
client_postcode,
client_woonplaats,
client_contactpersoon,
client_diagnose,
datun_aanmaak)
VALUES (:voornaam,
:achternaam.
:geboortedatum,
:geslacht,
:adres,
:postcode,
:woonplaats,
:contactpersoon,
:diagnose,
:datumaanmaak)
INSERT INTO verzorgers(
wat_is_verzorger,
voornaam_verzorger,
achternaam_verzorger,
geboortedatum_verzorger,
email_verzorger,
geslacht_verzorger,
adres_verzorger,
postcode_verzorger,
woontplaats_verzorger,
tel1_verzorger,
tel2_verzorger,
datum_aanmaak
)
VALUES(
:watisverz
:voornaamverz,
:achternaamverz,
:geboortedatumverz,
:emailverz,
:geslachtverz:
:adresverz,
:postcodeverz,
:woonplaatsverz,
:tel1verz,
:tel2verz,
:datumaanmaak
)
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':voornaam', $_POST['voornaam'], PDO::PARAM_STR);
$stmt->bindParam(':achternaam', $_POST['achternaam'], PDO::PARAM_STR);
$stmt->bindParam(':geboortedatum', $geboortedatum, PDO::PARAM_INT);
$stmt->bindParam(':geslacht', $_POST['geslacht'], PDO::PARAM_STR);
$stmt->bindParam(':adres', $_POST['adres'], PDO::PARAM_STR);
$stmt->bindParam(':postcode', $_POST['postcode'], PDO::PARAM_INT);
$stmt->bindParam(':woonplaats', $_POST['woonplaats'], PDO::PARAM_STR);
$stmt->bindParam(':contactpersoon', $_POST['contactpersoon'], PDO::PARAM_STR);
$stmt->bindParam(':diagnose', $_POST['diagnose'], PDO::PARAM_INT);
$stmt->bindParam(':datumaanmaak', $_POST['datum_toetreding'], PDO::PARAM_INT);
$stmt->execute();
}
catch(PDOException $e)
{
echo '<pre>';
echo 'Regel: '.$e->getLine().'<br>';
echo 'Bestand: '.$e->getFile().'<br>';
echo 'Foutmelding: '.$e->getMessage();
echo '</pre>';
} ?>
Now when the client and verzorger are created, they both get an unique ID.
Client had a column that stores the verzorger ID associated and vica versa.
Is it possible to make a query that also directly stores the IDs created?
EDIT:
ok maybe to difficult, maybe an answer to get only the client id in verzorger?:)
How about something like this (TableAID and TableBID are both AUTO_INCREMENT columns):
INSERT INTO TableA
(SomeColumn)
VALUES
('Blah');
SET #TableAID = LAST_INSERT_ID();
INSERT INTO TableB
(TableAID, AnotherColumn)
VALUES
(#TableAID,'Foobar');
SET #TableBID = LAST_INSERT_ID();
UPDATE TableA
SET TableBID = #TableBID
WHERE TableAID = #TableAID;
What you can do is create a function that queries against a sequence generator:
create function foo returns int
Begin
Declare nextValue int
Set nextValue = SELECT NEXT VALUE FOR mySequence;
End
return (nextValue);
Which would allow you to pass around the value returned from this sequence and you could know "ahead" of time what the values were going to be.
EDIT
Please understand how concurrency works and use either pessimistic or optimistic locking. While this should be obvious, some feel as though it is necessary to include.

How can I use ON DUPLICATE KEY UPDATE in PDO with mysql?

DETAILS
I am doing a single insert for the expiry of a new or renewed licence. The time period for the expiry is 2 years from the insertion date.
If a duplicate is detected, the entry will be updated such that the expiry equals the remaining expiry plus 2 years.
Regarding duplicates, in the example below there should only be one row containing user_id =55 and licence=commercial.
TABLE: licence_expiry
--------------------------------------------------------
| user_id | licence | expiry |
--------------------------------------------------------
| 55 | commercial | 2013-07-04 05:13:48 |
---------------------------------------------------------
user_id (int11), licence (varchan50), expiry (DATETIME)
I think in mysql you would write it something like this (Please note that I haven't checked whether the code works in mysql. )
INSERT INTO `licence_expiry`
(`user_id`, `licence`, `expiry`)
VALUES
(55, commercial, NOW()+ INTERVAL 2 YEAR)
ON DUPLICATE KEY UPDATE
`expiry` = `expiry` + INTERVAL 2 YEAR
QUESTION: How can I do this with PDO? I've written a rough outline of what I think I will use, but I'm not sure what to write for the expiry value for the ON DUPLICATE KEY UPDATE.
$sql = "INSERT INTO $table (user_id, licence, expiry)
VALUES (
:user_id,
:licence,
:expiry)
ON DUPLICATE KEY UPDATE expiry = Something";
try {
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':user_id', $userID, PDO::PARAM_INT);
$stmt->bindParam(':licence',$licence, PDO::PARAM_STR);
$stmt->bindParam(':expiry',$expiry, PDO::PARAM_STR);
$stmt->execute();
//$stmt->closeCursor(); //use this instead of $dbh = null if you will continue with another DB function
$dbh = null;
}
catch(PDOException $e)
{
$error=$e->getMessage();
}
Any help is much appreciated.
You can use MySQL's VALUES() function:
In an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the VALUES(col_name) function in the UPDATE clause to refer to column values from the INSERT portion of the statement. In other words, VALUES(col_name) in the UPDATE clause refers to the value of col_name that would be inserted, had no duplicate-key conflict occurred.
Therefore, in your case:
ON DUPLICATE KEY UPDATE expiry = VALUES(expiry)
Alternatively, you can create a fourth parameter to which you bind $expiry again:
$sql = "INSERT INTO $table (user_id, licence, expiry)
VALUES (
:user_id,
:licence,
:expiry)
ON DUPLICATE KEY UPDATE expiry = :another";
try {
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':user_id', $userID , PDO::PARAM_INT);
$stmt->bindParam(':licence', $licence, PDO::PARAM_STR);
$stmt->bindParam(':expiry' , $expiry , PDO::PARAM_STR);
$stmt->bindParam(':another', $expiry , PDO::PARAM_STR);
$stmt->execute();
// etc.
I know you have answer below, but i had same problem and my solution looks quite different but it works for me so if you want to use different statement of using insert in mysql with explicit binding values to columns you can try this code
$sql = "
INSERT INTO
$table
SET
user_id = :user_id,
licence = :licence,
expiry = :expiry
ON DUPLICATE KEY UPDATE
expiry = :expiry
";
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindValue('user_id', $userID , PDO::PARAM_INT);
$stmt->bindValue('licence', $licence, PDO::PARAM_STR);
$stmt->bindValue('expiry' , $expiry , PDO::PARAM_STR);

MYSQL copy row to another identical table with AUTO_INCREMENT id field

I have a movie database where movies are inserted into a table named titles with an AUTO_INCREMENT primary key named titles_id. Users can submit movies anonymously which are inserted into a separate identical table named titles_anon. After reviewing entries in titles_anon I want to insert them into titles but the id column is causing problems
I tried this:
INSERT INTO titles SELECT * FROM titles_anon WHERE
title_id='$title_id';
I either get a duplicate key error, or if the title_id does not already exist in titles it inserts OK but uses the titles_anon id instead of a new AUTO_INCREMENT value which I want.
How do I copy a row between tables when both tables have an AUTO_INCREMENT primary key?
INSERT INTO titles
(column_name1, column_name2, column_name3, column_name4,...)
SELECT title_id, col2, col3, col4,..
FROM titles_anon
WHERE title_id = '$title_id';
You define your fields in SELECT, but omit the PK and add the same fields to INSERT!
You can omit the id column completely, let mysql generate it for you. This need a little longer SQL to specify the exact columns you want to insert.
INSERT INTO titles (columns-other-than-the-primary-key)
SELECT columns-of-the-same-order FROM titles_anon
In PHP you can do something similar to:
$rs = mysql_query("select * from table_orig where RowID=$IDToCopy",$db_conn);
$row = mysql_fetch_assoc($rs);
$sql = '';
$fields = '';
foreach($row as $k => $v){
if($k == "RowID") continue;
$sql .= ",'$v'";
$fields .= ",$k";
}
$sql = "insert into table_copy (".substr($fields,1).") values (".substr($sql,1).")";
mysql_query($sql,$db_conn);
/* copy table with primary key to another table */
$table_old='colaboradores'; // your table old
$table_new='colaboradores2'; //your table new
// sql all columns withou primary key (column_key <> 'pri'
$rs=mysql_query("select column_name from INFORMATION_SCHEMA.COLUMNS
where table_name = '$table_old' and column_key <> 'pri' AND
table_schema = 'your database'");
// get all columns
$rows = mysql_fetch_assoc($rs);
$fields = '';
// mount fields in line
foreach ($rows as $k => $v) {
$fields .= ",$v[0]";
}
// remove first comma
$fields = substr($fields,1);
echo "Sintaxe for Create table in Mysql";
echo "CREATE TABLE $table_new SELECT $fields FROM $table_old ";
echo "Sintaxe for Insert from old table to new table Mysql";
echo "INSERT INTO $table_new $fields SELECT $fields FROM $table_old";