I want to get the the primary key (auto_increment) for the latest record to use it as a foreign key in the other table. When I use the SCOPE_IDENTITY() as a pdo parameter, I get the error:
Call to undefined function SCOPE_IDENTITY().
When I use it as a direct value, the statement always rolls back.
Is my code correct?
if (empty($errors)) {
$sqlconnection = new SqlConnection();
$conn = $sqlconnection->db_connect();
if ($conn) {
if (sqlsrv_begin_transaction($conn) === false ) {
$errors[] = "Cant start transaction.";
} else {
// Query1
$query1 = "INSERT INTO [RC.table1] (terminname, datum) VALUES (?, ?)";
$params1 = array($eventname, $eventdate);
$stmt1 = sqlsrv_query($conn, $query1, $params1);
//Query2
$query2 = "INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), ?)";
$params2 = array($_SESSION['mandant_id']);
$stmt2 = sqlsrv_query($conn, $query2, $params2);
if($stmt1 && $stmt2) {
sqlsrv_commit( $conn );
echo "Transaction committed.<br />";
} else {
sqlsrv_rollback( $conn );
echo "Transaction rolled back.<br />";
}
}
} else {
$errors[] = "Cant connect to database.";
}
}
Try this solution: replace
$query2 = "INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), ?)";
with this:
$query2 = "DECLARE #LastID INT; SET #LastID = SCOPE_IDENTITY(); INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES (#LastID, ?)";
Also, for #LastID variable definition (DECLARE #LastID INT) please use the same data type as data type of appointment_id column. In this example, I assumed that #LastID's type is INT.
Edit: You could create the following stored procedure with TRY ... CATCH:
CREATE PROCEDURE dbo.Insert_Table1Table2
(
#terminname NVARCHAR(50),
#datum DATE,
#mandant_id INT
)
AS
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
INSERT INTO [RC.table1] (terminname, datum) VALUES (#terminname, #datum)
DECLARE #appointment_id INT;
SET #appointment_id = SCOPE_IDENTITY();
INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES (#appointment_id, #mandant_id)
END TRY
BEGIN CATCH
SELECT
DECLARE #ErrorMessage NVARCHAR(2048);
SET #ErrorMessage = ERROR_MESSAGE();
RAISERROR(#ErrorMessage, 16, 1)
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
END
Note: You should replace every type and max. length with the proper type and length.
BEGIN TRAN T1;
INSERT INTO [RC.table1] (terminname, datum) VALUES ('alibaba', '24.02.2014');
BEGIN TRAN T22
INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), '0200')
COMMIT TRAN T1;
COMMIT TRAN T2;
that works perfectly in the studio. dont know, why I cant get the identity in the php transaction.
By the way, while that code MIGHT work, I would suggest the following changes...
$query1 = "INSERT INTO [RC.table1] (terminname, datum) VALUES (?, ?);select ##identy"
now, retrieve the result (which will be the new key added) and pass it as a parameter to the next SQL call.
Related
My project is a simple attendance record for my small school. I am submitting entry and exit logs through an online form, and writing them to a database with this query:
$sql = "INSERT INTO table_one (first_name, last_name, location)
VALUES ('$first_name', '$last_name', '$location')";
It works fine - so far so good.
At the same moment I would like to write some of this submitted information to another table in the same database. This query works fine by itself when standing alone:
$sql = "UPDATE another_table SET location='$location' WHERE first_name='$first_name'";
However my problem is how to make them both happen, in sequence. Just listing them successively doesn't work:
$sql = "INSERT INTO table_one (first_name, last_name, location) VALUES
('$first_name', '$last_name', '$location')";
$sql = "UPDATE personnel_table SET location='$location' WHERE
first_name='$first_name'";
What is the most effective (and safest) way to combine both commands so that they execute together?
You need to use transaction so that if one query fail, both should fail. Only if both query success that it will add/update the database.
$db= new PDO('mysql:host=localhost; dbname=test', $user, $pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$db->beginTransaction();
$sh = $db->prepare("INSERT INTO table_one (first_name, last_name, location) VALUES (?, ?, ?)");
$sh->execute([$first_name, $last_name, $location]);
$sh = $db->prepare("UPDATE personnel_table SET location=? WHERE first_name=?");
$sh->execute([$location, $first_name]);
$db->commit();
} catch ( Exception $e ) {
$db->rollBack();
}
for this problem you must use trigger option in database (forEx mysql).
trigger is like an event. when insert in on table automate update second table. forEx:
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
FOR EACH ROW SET #sum = #sum + NEW.amount;
Query OK, 0 rows affected (0.01 sec)
this trigger that is a object for account table. update #sum variable and then use for update second table
You can create a trigger like below:
delimiter #
create trigger after_ins_trig after insert on first_table
for each row begin
UPDATE second_table
SET new.location=old.location
WHERE new.first_name=old.first_name end#
delimiter ;
You can check id in where clause.
Why not this:
Table: teraz
Create Table: CREATE TABLE `teraz` (
`col` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
//
<?php
$last_name = 77;
$conn = new mysqli('localhost','root','','shopping');
$sql = "INSERT INTO teraz VALUES ('{$last_name}')";
$sql2 = "SELECT * FROM teraz";
$conn->query($sql);
$result = $conn->query($sql2);
$x = $result->fetch_assoc() ;
echo $x['col'];
?>
?
Ok .. Here is the thing. I want to list users logged on and change their status when logged out. This works perfect. I created a table for that called tblaudit_users. The existing users I SELECT from a tbl_users table.
What I want, is that if an user already exists in the tblaudit_users table it will UPDATE the LastTimeSeen time with NOW(). But instead of updating that record, it creates a new record. This way the table will grow and grow and I want to avoid that. The code I use for this looks like:
+++++++++++++++++++
$ipaddress = $_SERVER['REMOTE_ADDR'];
if(isset($_SESSION['id'])){
$userId = $_SESSION['id'];
$username = $_SESSION['username'];
$achternaam = $_SESSION['achternaam'];
$district = $_SESSION['district'];
$gemeente = $_SESSION['gemeente'];
$query = $db->prepare("SELECT * FROM tblaudit_users WHERE username = '{$username}' AND active = '1' LIMIT 1");
$query->execute();
foreach($query->fetchAll(PDO::FETCH_OBJ) as $value){
$duplicate = $value->username;
}
if($duplicate != 1){
$insert = $db->prepare("
INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
");
$insert->execute();
} elseif($duplicate = 1){
$update = $db->prepare("UPDATE tblaudit_users SET LastTimeSeen = NOW(),status = '1' WHERE username = '{$username}'");
$update->execute();
} else {
header('Location: index.php');
die();
}
}
I am lost and searched many websites/pages to solve this so hopefully someone here can help me? Thanks in advance !!
UPDATE:
I've tried the below with no result.
+++++
$insert = $db->prepare("
INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
ON DUPLICATE KEY UPDATE set LastTimeSeen = NOW(), status = '1'
");
$insert->execute();
Ok. I altered my query and code a little:
$query = $db->prepare("SELECT * FROM tblaudit_users WHERE username = '{$username}' LIMIT 1");
$query->execute();
if($query){
$insert = $db->prepare("
INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
ON DUPLICATE KEY UPDATE set LastTimeSeen = NOW(), status = '1'
");
$insert->execute();
} else {
header('Location: index.php');
die();
}
}
I also added a UNIQUE key called pid (primary id). Still not working.
Base on http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html, don't use 'set' in update syntax
example from the page:
INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=9;
Several issues:
You test on $query, but that is your statement object, which also will be valid even if you have no records returned from the select statement;
There can be issues accessing a second prepared statement before making sure the previous one is closed or at least has all its records fetched;
There is a syntax error in the insert statement (set should not be there);
For the insert ... on duplicate key update to work, the values you provide must include the unique key;
SQL injection vulnerability;
Unnecessary split of select and insert: this can be done in one statement
You can write your test using num_rows(). To get a correct count call store_result(). Also it is good practice to close a statement before issuing the next one:
$query = $db->prepare("SELECT * FROM tblaudit_users
WHERE username = '{$username}' LIMIT 1");
$query->execute();
$query->store_result();
if($query->num_rows()){
$query->close();
// etc...
However, this whole query is unnecessary when you do insert ... on duplicate key update: there is no need to first check with a select whether that user actually exists. That is all done by the insert ... on duplicate key update statement.
Error in INSERT
The syntax for ON DUPLICATE KEY UPDATE should not have the word SET following it.
Prevent SQL Injection
Although you use prepared statements (good!), you still inject strings into your SQL statements (bad!). One of the advantages of prepared statements is that you can use arguments to your query without actually injecting strings into the SQL string, using bind_param():
$insert = $db->prepare("
INSERT INTO tblaudit_users (user_id, username, achternaam, district,
gemeente, ipaddress, LastTimeSeen, status)
VALUES (?, ?, ?, ?, ?, ?, NOW(), '1')
ON DUPLICATE KEY UPDATE LastTimeSeen = NOW(), status = '1'
");
$insert->bind_param("ssssss", $userId, $username, $achternaam,
$district, $gemeente, $ipaddress);
$insert->execute();
This way you avoid SQL injection.
Make sure that user_id has a unique constraint in the tblaudit_users. It does not help to have another (auto_increment) field as primary key. It must be one of the fields you are inserting values for.
The above code no longer uses $query. You don't need it.
I found the issue
if(isset($_SESSION['id'])){
$userId = $_SESSION['id'];
$username = $_SESSION['username'];
$achternaam = $_SESSION['achternaam'];
$district = $_SESSION['district'];
$gemeente = $_SESSION['gemeente'];
$query = $db->prepare("SELECT * FROM tblaudit_users WHERE user_id = '{$userId}' LIMIT 1");
$query->execute();
if($query->rowcount()<1){
$insert = $db->prepare("
INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
");
$insert->execute();
} elseif($query->rowcount()>0) {
$update = $db->prepare("UPDATE tblaudit_users SET LastTimeSeen = NOW(),status = '1' WHERE user_id = '{$userId}'");
$update->execute();
} else {
header('Location: index.php');
die();
}
}
Instead of using $username in my query, I choose $userId and it works.
What is the proper way to reference the array components from fetch_assoc() so that they can be inserted into another table?
Here is my current code:
$sql_read = "SELECT id, data1, data2, date FROM `table1`";
$result = $mysqli->query($sql_read);
if ($result !== false) {
$rows = $result->fetch_all();
}
while ($row = $result->fetch_assoc()){
$sql_write = "INSERT INTO `table2`.`load_records` (`id`, `data1`,`data2`,`date`) VALUES ('.$row['id']', '.$row['data1']', '.$row['data2']', '.$row['date']', NULL);";
}
As suggested in my comment, first your select statement should be:
"SELECT id, data1, data2, date FROM `table1`";
Furthermore, the insert statement should be (see the use of concatenation of strings):
"INSERT INTO `table2`.`load_records` (`id`, `data1`,`data2`,`date`) VALUES ('".$row['id']."', '".$row['data1']."', '".$row['data2']."', '".$row['date']."', NULL);";
There are some errors in your script, as already pointed out.
But you might also be interested in the INSERT INTO ... SELECT variant of the INSERT syntax.
<?php
$query = '
INSERT INTO
table2
(`id`, `data1`,`data2`,`date`)
SELECT
`id`, `data1`,`data2`,`date`
FROM
table1
';
$result = $mysqli->query($query);
if ( !$result ) {
trigger_error('error: ' . $mysqli->error, E_USER_ERROR);
}
else {
echo $mysqli->affected_rows, ' rows have been transfered';
}
You have an extra field in the VALUES that is not referenced in the INTO and the concatenation of the row data is incorrect;
$sql_write = "INSERT INTO `table2`.`load_records`
(`id`, `data1`,`data2`,`date`)
VALUES ('.$row['id'].', '.$row['data1']', '.$row['data2']', '.$row['date']', NULL);";
should be:
$sql_write = "INSERT INTO `table2`.`load_records`
(`id`, `data1`,`data2`,`date`)
VALUES ('".$row['id']."', '".$row['data1']."', '".$row['data2']."', '".$row['date']."');";
Or you need to update the INTO to include an extra column that accepts NULL
See also:
The PHP reference on mysqli_result::fetch_assoc
$fname = addslashes($fname);
$lname = addslashes($lname);
$dob = addslashes($dob);
$email = $_POST['email'];
$sql =
"INSERT INTO subscriber
(fname, lname, dob)
VALUES
('".$fname."', '".$lname."', '".$dob."')
WHERE email='".$email."'";
$register = mysql_query($sql) or die("insertion error");
I am getting error in sql query "insertion error". Query is inserting data into DB after removing WHERE statement. What is the error.
You can't use where in an insert statement. You might be thinking of an update instead?
$sql = "update subscriber set fname='".$fname."', lname = '".$lname."', dob = '".$dob."' WHERE email='".$email."'";
If your email is a unique value, you can also combine an insert with an update like this:
insert into
subscriber (fname, lname, dob, email)
values ('".$fname."', '".$lname."', '".$dob."', '".$email."')
on duplicate key update set fname='".$fname."', lname='".$lname."', dob='".$dob."'
This second syntax will insert a row if there isn't one with a matching email (again, this has to be set to a unique constraint on the table) and if there is one there already, it will update the data to the values you passed it.
Basically INSERT statement cannot have where. The only time INSERT statement can have where is when using INSERT INTO...SELECT is used.
The only syntax for select statement are
INSERT INTO TableName VALUES (val1, val2, ..., colN)
and
INSERT INTO TableName (col1, col2) VALUES (val1, val2)
The other one is the
INSERT INTO tableName (col1, col2)
SELECT col1, col2
FROM tableX
WHERE ....
basically what it does is all the records that were selected will be inserted on another table (can be the same table also).
One more thing, Use PDO or MYSQLI
Example of using PDO extension:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
?>
this will allow you to insert records with single quotes.
Oops !!!! You cannot use a WHERE clause with INSERT statement ..
If you are targeting a particular row then please use UPDATE
$sql = "Update subscriber set fname = '".$fname."' , lname = '".$lname."' , dob = '".$dob."'
WHERE email='".$email."'";
$register = mysql_query($sql) or die("insertion error");
I have variable set to NULL that im trying to insert into a database but for some reason they keep getting submitted as '0'. Im positive that column im trying to inset into allows NULL and that the default is set to to NULL. Heres my code:
$insert = NULL;
$query = mysql_query("INSERT INTO `table1` (column1) VALUES ('$insert')") or die(mysql_error());
Warning:
Please, don't use mysql_* functions for new code. They are no longer maintained and the community has begun the deprecation process. Instead you should learn about prepared statements and use either PDO or MySQLi.
IF you want it to be NULL (and you really really still want to use mysqli_*) in the database you can do the following:
$insert = NULL;
$query = mysql_query("INSERT INTO `table1` (column1) VALUES ("
.(($insert===NULL)?
"NULL":
"'".mysql_real_escape_string($insert)."'").
")") or die(mysql_error());
But this could lead to nefarious SQL injection and is not recommended.
See Bobby Tables
So: all in all you should be using prepared statements.
You can use MySQLi like so:
$dbHandle = new mysqli(...);
$query = "INSERT INTO `table1` (column1) VALUES (?)";
$statement = $dbHandle->prepare($query);
if($statement){
$statement->bind_param('s', $insert);
if(!$statement->execute()){
echo "Statement insert error: {$statement->error}";
}
$statement->close();
}
else {
echo "Insert error: {$dbHandle->error}";
}
Try this for static query:
$query = mysql_query("INSERT INTO `table1` (column1) VALUES (NULL)") or die(mysql_error());
Using Variable :
$insert= NULL;
$insert = ($insert===NULL)? 'NULL' : "'$insert'";
mysql_query("INSERT INTO `table1` (column1) VALUES ($insert)") or die(mysql_error());
Try without the quotes;
$query = mysql_query("INSERT INTO `table1` (`column1`) VALUES (".$insert.")") or die(mysql_error());
The query should be;
INSERT INTO table1 (column1) VALUES (NULL);