$prepared = $db->prepare("
SET #content = ?;
CALL add_interest_if_not_exists( #content );
SET #iid = (SELECT interests_id
FROM interests
WHERE content = #content);
REPLACE INTO profile_interests (user_id, interests_id, likes)
VALUES (
?,
#iid,
?
)
");
echo $db->error;
The error is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CALL add_interest_if_not_exists( #content ); SET #iid = (SELECT i' at line 3
The query works using MySQL workbench (hard-coded values). Why won't it in my prepared statement...
This is not a single query but a set of queries.
Therefore you have to run them one by one, each with separate query() or prepare()/execute() call.
Why not use a stored procedure?
CREATE PROCEDURE add_user_interest(p_content varchar(200), p_user_id int,p_likes int)
BEGIN
CALL add_interest_if_not_exists( p_content );
SET #iid = (SELECT interests_id
FROM interests
WHERE content = p_content);
REPLACE INTO profile_interests (user_id, interests_id, likes)
VALUES (
p_user_id,
#iid,
p_likes
);
END
End you will call as single prepared statement
$prepared = $db->prepare("CALL add_user_interest( ?, ? , ? )");
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).
$query=mysqli_query($conn,"INSERT INTO bus_info(bus_id,route_num,school_name) values('$BusNum','$RouteNum','$SchoolName'); INSERT INTO bus_loc(bus_id,lat,lon) values ((SELECT bus_id from bus_info where bus_info.bus_id='$BusNum'),'$latitude','$longitude')");
PHP
$BusNum = $_POST["BusNum"];
$SchoolName = $_POST["SchoolName"];
$RouteNum = $_POST["RouteNum"];
$latitude = $_POST["lat"];
$longitude = $_POST["lng"];
Database is connected i.e. returned true.enter code here
Fails with :
Error sending data:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near INSERT INTO bus_loc(bus_id,lat,lon) values ((SELECT bus_id from bus_info where b at line 1
From: http://php.net/manual/de/mysqli.query.php#87203
mysqli::query() can only execute one SQL statement.
Use mysqli::multi_query() when you want to run multiple SQL statements within one query.
How to use mysqli_multi_query: http://php.net/manual/de/mysqli.multi-query.php
For better understanding split query into two parts and use them like :-
$query = mysqli_query($conn,"INSERT INTO bus_info (bus_id,route_num,school_name) values('$BusNum','$RouteNum','$SchoolName')");
$query2 = mysqli_query($conn,"INSERT INTO bus_loc (bus_id,lat,lon) values ((Select bus_id from `bus_info` where bus_id = '$BusNum'),'$latitude','$longitude')");
This query is missing a where clause condition
SELECT bus_id from bus_info where b
change it to like:
SELECT bus_id from bus_info where b = 'something'
but you should not execute two queries like this but execute this first save the result in a variable and then execute the next one like
$query = SELECT bus_id from bus_info where b = 'something'
$saved = $mysqli_query($yourconnection, $query);
$row = mysqli_fetch_assoc();
$fetched = row['columnnamehere'];
and then
INSERT INTO bus_loc(bus_id,lat,lon) values ('$fetched');
I'm trying to check if a record already exists in my table and if it doesn't I want to execute an insert... using a prepared statement. Can anyone tell me what's wrong below? I've written the code with error checking and it basically says the query is poo :) I am atrocious when it comes to SQL and pretty much anything programming related so I really do appreciate any wisdom that shared on this dodgy looking quest... Thanks!
$mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);
$timestamp = time();
$stmt = $mysqli->prepare("IF NOT EXISTS (SELECT id FROM course_licence_cart WHERE userid = ? AND courseid = ? AND lmsid = ?) BEGIN INSERT INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on) VALUES (?, ?, ?, ?, ?) END");
foreach($_POST['assignTo'] as $assignTo){
$stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
$stmt->execute();
}
FYI: This takes place after a form submission, I've checked ALL of the variables and they're all good, and the process itself works perfectly (I have it working without the IF NOT EXISTS), it's just this new query type mixed with prepared statements that has totally thrown me off.
-- UPDATE --
I ran the following directly:
IF NOT EXISTS (SELECT `id` FROM `course_licence_cart` WHERE `userid` = '175' AND `courseid` = '1' AND `lmsid` = '1') BEGIN INSERT INTO `course_licence_cart` (`lmsid`, `userid`, `courseid`, `assigned_by`) VALUES ('1', '175', '1', '175') END
In which I get the error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF NOT EXISTS (SELECT `id` FROM `course_licence_cart` WHERE `userid` = '175' AND' at line 1
First of all the root of the error has nothing to do with prepared statements. It's just you can't use IF, BEGIN ... END blocks and other constructs out of the scope of a stored routine (procedure, function, trigger, event).
To prevent duplicates you can leverage INSERT IGNORE like so
$stmt = $mysqli->prepare("INSERT IGNORE INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on) VALUES (?, ?, ?, ?, ?)");
foreach($_POST['assignTo'] as $assignTo){
$stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
$stmt->execute();
}
In order for this to work you have to have a unique constraint defined.
CREATE UNIQUE INDEX index_name
ON course_licence_cart (userid, courseid, lmsid);
Here is SQLFiddle demo
Now your code (after correcting syntax) could've worked in a stored procedure like so
DELIMITER //
CREATE PROCEDURE add_to_cart(IN _lmsid INT, IN _userid INT, _courseid INT, IN _assigned_by INT, IN _assigned_on DATETIME)
BEGIN
IF NOT EXISTS (SELECT *
FROM course_licence_cart
WHERE userid = _userid
AND courseid = _courseid
AND lmsid = _lmsid) THEN
INSERT INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on)
VALUES (_lmsid, _userid, _courseid, _assigned_by, _assigned_on);
END IF;
END//
DELIMITER ;
Here is SQLFiddle demo
In this case php code would look like
$stmt = $mysqli->prepare("CALL add_to_cart (?, ?, ?, ?, ?)");
foreach($_POST['assignTo'] as $assignTo){
$stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
$stmt->execute();
}
Since you're coding in PHP, one thing to consider is doing a sql query to SELECT from that table, if nothing is returned, run an insert query.
I'm sure it can be doing through SQL, but I personally don't know how.
Good luck, sorry if this doesn't help.
in MYSQL there are 4 types of inserts available.
1)INSERT 2)INSERT IGNORE 3)INSERT ON DUPLICATE KEY 4)REPLACE
Please explore on them.
As far as I can understand your specific case can be handled by INSERT IGNORE command.
Note : I am assuming here that Mysqli is same as MYSQL
Update: now I know that mysqli is interface to MYSQL.But the concept of insert ignore will still be same.
example to understand use of INSERT IGNORE
consider below table.
CREATE TABLE person_tbl ( first_name CHAR(20) NOT NULL, last_name CHAR(20) NOT NULL, sex CHAR(10), PRIMARY KEY (last_name, first_name) );
here firstname&lastname forms primary key
now we run query
mysql> INSERT INTO person_tbl VALUES( 'Jay', 'Thomas');
it will add one row in table
if we will run the above sql it will fail with duplicate record exception.to prevent this exception we have 2 options
1)check if record already exists,if not then insert record.... we have to fire select and then insert query.
2) fire INSERT IGNORE SQL.. it will check the if record exist in table if exist then it will not insert record ,if not then inserts record.
for e.g
if we run query
mysql> INSERT IGNORE INTO person_tbl VALUES( 'Jay', 'Thomas');
this sql will not insert any record ..as record already exists
but
mysql> INSERT IGNORE INTO person_tbl VALUES( 'Vijay', 'Thomas');
it will insert one record in table.
I am unable to understand on how to apply insert query with select statement:
I have gone through this question also:
MySQL INSERT from a SELECT with PDO
But where is the VALUES part??
Like I have this query to insert in Mysql and here I use Values also:
$db_conn->beginTransaction();
$query = $db_conn->prepare('INSERT INTO mytable (name, user_id) VALUES(:sname, :uid)');
foreach($UploadData AS $DataValue)
{
$query->execute(array(':sname' => $DataValue['Name'],':uid' =>$_SESSION['uid']));
}
$db_conn->commit();
My motto is to check if the name exists with the same uid it shouldn't import the data otherwise it should. But Where are the values part :/ I am blind :P
EDIT1: From MySQL INSERT from a SELECT with PDO
How will this code block work if no VALUES is supplied?
$sql_enc = '
INSERT INTO sessionid (enc_id, enc_pass, enc_date)
(SELECT AES_ENCRYPT(username, :aeskey), AES_ENCRYPT(pwd, :aeskey), DATE_ADD(NOW(), INTERVAL 15 SECOND) FROM users WHERE username = :username)
';
$res_enc = $pdo->prepare($sql_enc);
$res_enc->bindParam(':aeskey', $aeskey);
$res_enc->bindParam(':username', $username);
$res_enc->bindParam(':pwd', $username);
$res_enc->execute();
$res_enc = null;
There are two valid INSERT syntax:
INSERT
INTO `table` [(field1, field2)]
VALUES ( 'val1', 'val2' )
Or
INSERT
INTO `table` [(field1, field2)]
SELECT 'val1', 'val2'
the selected columns are your value fields.
#comments:
Replace:
http://dev.mysql.com/doc/refman/5.5/en/replace.html
Procedures:
http://dev.mysql.com/doc/refman/5.6/en/create-procedure.html
You are defining the parameters :sname and :uid in your loop. The method execute takes the params and "put them" inside your query before executing this one.
On other words, the query is compiled when you call prepare() and the parameters are applied when you call execute().
Edit:
Ok I didn't understand.
The query includes a "SELECT" part which gives the values to insert. With SELECT you must not write "VALUES", as the documentation says:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
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' ) );