MySQL query fails on integrity constraint violation - mysql

This query keeps failing with
Integrity constraint violation: 1048 Column 'login_name' cannot be null
My insert statement is...
$insertUserQuery = 'INSERT INTO `users` (
`login_name`,
`password`,
`first_name`,
`last_name`,
`company_name`,
`company_address`,
`country`,
`email`,
`phone_number`,
`agency_type`,
`sold_before`,
`authorised`,
`current_module`
)
VALUES (
:login_name, :login_password, :first_name, :last_name, :company_name, :company_address, :country, :email, :phone_number, :agency_type, :sold_before, 0, 0);';
$bindings = array(':login_name' => $loginName,
':login_password' => sha1($password . Config::PASSWORD_SALT),
':first_name' => $firstName,
':last_name' => $lastName,
':company_name' => $companyName,
':company_address' => $companyAddress,
':country' => $country,
':email' => $emailAddress,
':phone_number' => $phone,
':agency_type' => null,
':sold_before' => null
);
print_r($bindings);
Db::query($insertUserQuery, $bindings);
My database class can be found at another question. The print_r() tells me that the array definitely has a value.
May it have something to do with me using the word 'password' which is also a MySQL function?
Does PDO support prepared statements with INSERT in the same fashion as it does with SELECT?
Do I need to quote around the values, example ':login_name'?

PDO::query doesn't support prepared statement syntax does it? Give PDO::prepare and PDOStatement::execute a read. You probably want something like:
$insertUserQuery = 'INSERT INTO `users` (`login_name`, ...) ' .
'VALUES (:login_name, ...);';
$bindings = array(':login_name' => $loginName, ...);
$stmt = Db::prepare($insertUserQuery);
$stmt->execute($bindings);
You can also call $stmt->bindValue() instead of building an array of bindings. I think that explicitly binding each value is a little nicer since you can verify the types right there.
EDIT: sorry jcinacio, I didn't see that your comment was almost identical until after I posted.

Related

How to check if record was changed on db after inserting data?

I insert some data from a db.table1 to db.table2 with a cronjob which runs every minutes. But I need to check if any record has changed after data is inserted on table2 because I get some wrong data on this table when data is inserted.
this is crontab function
$data = DB::connection('mysql2')
->table('students')
->where('status', '=', 'Y')
->get();
foreach ($data as $key => $aStudent) {
// Check if student_id duplicated
$existing_data_in = DB::table('student')
->where("student_id", $aStudent->student_id)
->first();
if (! $existing_data_in) {
DB::connection('mysql')->table('student')->insert([
"first_name" =>$aStudent->first_name,
"last_name" =>$aStudent->last_name,
"age" =>$aStudent->age,
"student_id" =>$aStudent->student_id,
"created_at" =>$aStudent->created_at
]);
}
}
Log::info('Success, Data Updated');
Or maybe should I run cronjob rarely? My problem is when some record on table1 are filed with data and when this record goes to table2 are empty on table2. If I check same student_id on table1 is okay but on table2 are saved empty
i have loged my query on cronjob and this is what i get in case i find an empty filed on table 2. So last name on table 1 in this case is filled with really last name but on table 2 is inserted as empty and this is query (what hapend)
[2022-01-19 14:16:17] local.INFO: select `student_id` `first_name`, `last_name`, `age`, `created_at` from `students` where `student_id` = ? limit 1 [421]
// this comes from query where i check for dublicated lines i think
[2022-01-19 14:16:17] local.INFO: select * from `student` where `student_id` = ? limit 1 [421]
[2022-01-19 14:16:17] local.INFO: insert into `student`
(`student_id`, `first_name`, `last_name`, `age`, `created_at`) values
(?, ?, ?, ?, ?)
["421","name","","38","2022-01-19 14:13:35"]
If the tables contain created_at and updated_at columns, you can tell if a record has been updated by comparing the two columns.
->whereRaw('created_at != updated_at')->get();
You could wrap everything in a transaction to make sure it works as it should.
$data = DB::connection('mysql2')
->table('students')
->where('status', '=', 'Y')
->get();
$dataToInsert = $data->map(function ($item) {
return [
'first_name' => $item->first_name,
'last_name' => $item->last_name,
'age' => $item->age,
'student_id' => $item->student_id,
'created_at' => $item->created_at
];
})->all();
$columnsToCheck = ['student_id'];
$columnsToUpdate = [];
$conn = DB::connection('mysql');
$conn->beginTransaction();
try {
$conn->table('student')->upsert($dataToInsert, $columnsToCheck, $columnsToUpdate);
$conn->commit();
Log::info('Success');
} catch (\Exception $e) {
$conn->rollBack();
Log::error($e);
}
I'm using upsert. You can read more about it here.
https://laravel.com/docs/8.x/queries#upserts

Codeigniter database backup - Insert multiple rows without repeating “INSERT INTO”

I'm trying out to find a way to backup my database using Codeigniter "Database Utility" but without repeating “INSERT INTO”, I mean everything works perfectly, but when we see the generated sql file we see something like this:
INSERT INTO Membership (ID, FirstName, LastName, DOB)
VALUES (1, 'John', 'Smith', '5/5/1960')
INSERT INTO Membership (ID, FirstName, LastName, DOB)
VALUES (2, 'Hello", 'World", '4/9/1975')
INSERT INTO Account(ID, Type, Effective_Date, Status)
VALUES (1, 'Gold', GetDate(), 'Active')
INSERT INTO Account(ID, Type, Effective_Date, Status)
VALUES (2, 'Platinum', GetDate(), 'Inactive')
INSERT INTO Participant(ID, Code, Type)
VALUES (1, 002, 'A')
INSERT INTO Participant(ID, Code, Type)
VALUES (2, 002, 'A')
The which is so slow whenever we import in another database. I want to get something like this:
INSERT INTO #temp_table (1, 'John', 'Smith, '5/5/1960', 'Gold', 'Active', '002', 'A')
.
.
.
.
so on
using only one INSERT INTO, is there any way to achieve this? Thanks.
You can make use of CodeIgniter insert_batch() function
Follow this link here to see how it works:
Create a multi-dimensional array with field and values like this, and use codeigniter inset_batch() function to insert all these in a single query.
$data = array(
array(
'ID' => 1,
'FirstName' => 'John',
'LastName' => 'Doe',
'DOB' => '5/5/1960'
),
array(
'ID' => 2,
'FirstName' => 'John',
'LastName' => 'Smith',
'DOB' => '5/5/1960'
)
);
$this->db->insert_batch('temp_table', $data);
I understand your problem, Database Utility is quite slow also, due to string concatenation, if passthru() is enabled on your server, then mysqldump can be used, here is working code, which will export current database.
public function backup_current_db()
{
$db_user=$this->db->username;
$password=$this->db->password;
$db=$this->db->database;
$filename = $db . "-" . date("Y-m-d_H-i-s") . ".sql";
$mime = "application/octet-stream";
header( "Content-Type: " . $mime );
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
$cmd = "mysqldump -u '$db_user' --password='$password' --no-create-info --complete-insert '$db' ";
passthru( $cmd );
die();
}

SQL IF EXIST UPDATE ELSE INSERT prepared statement

I'm breaking my brains over this, i would realy appriciate help!
This is the code i have so far..
$conn = db_connect();
$sql = "INSERT INTO measurements
(`date`, `weight`, `waist`, `id`) VALUES (?,?,?,?)";
$stmt = $conn-> prepare($sql);
$stmt ->bind_param("sddi", $date, $_POST['weight'], $_POST['waist'], $user_id);
$stmt->execute();
$stmt->close();
$conn->close();
Its a prepared statement for an sql insert. Now i want to change it to a IF EXIST THEN UPDATE ELSE insert the way i am doing right now. something like this but then with a prepared statement:
IF EXISTS
(SELECT * FROM measurements WHERE user_id=’4’)
UPDATE measurements SET (`weight`=40, `waist`=45) WHERE user_id=’4’
ELSE
INSERT INTO measurements
VALUES (`date`='week 1', `weight`= 40, `waist`=45, `id`=4)
I found some articles on stackoverflow about the if EXIST then update else insert but i did not find it with a prepared statement in it that worked for me.
Thanks a thousand!
UPDATE:
i've changed it to dublicate key style.
$sql = "
INSERT INTO measurements (uniqueID, date, weight, waist)
VALUES ('$uniqueID', '$date', '$weight', '$waist')
ON DUPLICATE KEY UPDATE weight= '$weight', waist= '$waist'";
$conn->query($sql);
Now the second part of the question, how do i make this a prepared statement?
To implement Mr. Jones' solution as a mysqli prepared statement, you would code it thus:
$sql = "INSERT INTO measurements
(`uniqueID`, `date`, weight, waist)
VALUES
(?, ?, ?, ?)
ON DUPLICATE KEY
UPDATE weight = ?, waist = ?";
$stmt = $conn->prepare($sql);
$stmt ->bind_param("isdddd", $user_id, $date, $_POST['weight'], $_POST['waist'], $_POST['weight'], $_POST['waist']);
$stmt->execute();
A slightly cleaner implementation would be to use PDO:
$sql = "INSERT INTO measurements
(`uniqueID`, `date`, weight, waist)
VALUES
(:uniqueId, :date, :weight, :waist)
ON DUPLICATE KEY
UPDATE weight = :weight, waist = :waist";
/* $conn is a PDO object */
$stmt = $conn->prepare($sql);
$stmt->execute(array(':uniqueId' => $user_id, ':date' => $date, ':weight' => $_POST['weight'], ':waist' => $_POST['waist']));
Note that with named placeholders, you can use the same name in more than one place and only need to assign the value once.
MySQL's approach to this is INSERT ... ON DUPLICATE KEY UPDATE .... It works well; in particular it avoids race conditions if more than one database connection tries to hit the same row.
This requires the table that's the target of your UPSERT to have a meaningful unique index or primary key. It looks like your id is that key.
You can absolutely use parameter binding to present data to this.
You can read about it here. http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

Database Error Occurred Error Number: 1062

i tried to make option update three table with one execution for my CI with sql there, but why its still error?
this is the error warning:
A Database Error Occurred
Error Number: 1062
Duplicate entry '0' for key 1
UPDATE `t_publisher` SET `id_publisher` = NULL, `publisher` = NULL, `artis` = NULL, `id_label` = NULL WHERE `id_publisher` = '113'
this is the code:
function update($id_user=null)
{
if (($this->input->post('submit') == 'Update')){
$user=$this->input->post('username');
$pass=$this->input->post('userpassword');
$ussta=$this->input->post('userstatus');
$usty=$this->input->post('usertype');
$data = array(
'user_name' => $user,
'user_pass' => $pass,
'user_status' => $ussta,
'user_type' => $usty);
$this->db->where('user_id', $this->input->post('id'), $data);
$this->db->update("t_user",$data);
$data1 = array(
'id_publisher' => $id_publis,
'publisher' => $publis,
'artis' => $ar,
'id_label' => $id_lab);
$this->db->where('id_publisher', $this->input->post('id'), $data);
$this->db->update("t_publisher",$data1);
echo $this->db->last_query();
die();
$data2 = array(
'id_label' => $id_lab,
'label' => $label);
$this->db->where('id_label', $this->input->post('id'), $data);
$this->db->update("t_label",$data2);
echo $this->db->last_query();
die();
redirect("registrasi/reg");
}
$var['data'] = $this->db->query("select * from t_user where USER_ID= '$id_user'")->row_array();
$var1['data'] = $this->db->query("select * from t_publisher where id_publisher = '$id_publis'")->row_array();
$var2['data'] = $this->db->query("select * from t_label where id_label = '$id_lab'")->row_array();
$this->load->view('update', $var,$var1,$var2);
}
whats wrong with my code? please help. thanks before.
Your UPDATE clause is setting the id_publisher column to NULL, and, based on the name of the column and the error you're receiving, that column is the table's PRIMARY KEY with a setting of unsigned NOT NULL.
Because of this, when you do id_publisher = NULL, MySQL converts it to id_publisher = 0 due to the unsigned part. This will execute fine the first time, however, when you run it on a second row you will now be attempting to insert a second primary-key value of 0, which is not allowed.
Based on the location of the die() statement in your sample code, I'm assuming the following block is the culprit:
$data1 = array(
'id_publisher' => $id_publis,
'publisher' => $publis,
'artis' => $ar,
'id_label' => $id_lab);
$this->db->where('id_publisher', $this->input->post('id'), $data);
$this->db->update("t_publisher",$data1);
Here, your $id_publis variable is either empty or null.
I would suggest to either remove the id_publisher = NULL portion from the UPDATE clause which is as simple as removing 'id_publisher' => $id_publis, from the $data1 array, or rethink the reason you actually need to set it to null to begin with (in this case, would deleting the row be more beneficial?)

add values with 'on duplicate key'

I have the folowing array called $words
Array
(
[0] => Array
(
[token] => dwA
[pos] => *DII.7,8*
)
[1] => Array
(
[token] => nTr
[pos] => *DI.5,9*
)
[2] => Array
(
[token] => dwA
[pos] => *DI.2,8*
)
[3] => Array
(
[token] => nTr
[pos] => *DI.2,8*
))
I want to insert it with the following :
foreach ($words as $value)
{
$word = $value['token'];
$attestation = $value['pos'];
$insert="INSERT INTO Examples (Word, Attestation) VALUES ('$word', '$attestation')
mysql_query($insert) OR die(mysql_error());
}
The table 'Examples' has a key called ID with auto increasement;
the field word is 'unique'
what I want is that in the field 'Attestation' the values are added each time the 'word' is the same
so the result should be the following:
Id word Attestation
1 dwA *DII.7,8*, *DI.2,8*
2 nTr *DI.5,9*, *DI.2,8*
so I tried to add a 'on duplicate key' phrase
foreach ($words as $value)
{
$word = $value['token'];
$attestation = $value['pos'];
$insert="INSERT INTO Words2 (Word, Attestation) VALUES ('$word', '$attestation')
on duplicate key update Attestation =
";
mysql_query($insert) OR die(mysql_error());
}
but I can't figure out what I have to add after Attestation = so that the differents attestations are added one after the other, like for example : DI.5,9, DI.2,8
Or is the 'on duplicate key' not the correct way to do this?
Try this;
INSERT INTO Words2 (Word, Attestation) VALUES ('$word', '$attestation')
on duplicate key update Attestation = CONCAT(Attestation, ', ', '$attestation')
Although, it may a bit difficult to break those values apart later on. You may want to consider another table, so you can set up a one-to-many relationship.