active record omit insert when value exists - php

I normally parse a data array to the db obj as follows
$this->db->update('myTable', array('col1' => "foo", 'col2' => 'bar' ,'col3' => 'abc'), array('id' => $id));
Is there a way of only updating the columns that have a null value? Currently i'm having to run a query first and then loop through. Not very efficient.

Here are a couple of solutions:
$sql = 'UPDATE myTable SET col1 = IF(col1 IS NULL, ?, col1), col2 = IF(col2 IS NULL, ?, col2), col3 = IF(col3 IS NULL, ?, col3)';
$this->db->query($sql, ['foo', 'bar', 'abc']);
or
$this->db->set('col1', 'IF(col1 IS NULL, "foo", col1)', FALSE)
->set('col2', 'IF(col2 IS NULL, "bar", col2)', FALSE)
->set('col3', 'IF(col3 IS NULL, "abc", col3)', FALSE)
->update('myTable');

Related

Case Statement in Update Query - Medoo PHP Database framework

I want to convert this query into medoo:
$update_data = "UPDATE users SET `featured` = CASE WHEN `start_date` = '2022-08-10' AND `stop_date` = '2022-08-14' THEN '1' ELSE '0' END
";
I've tried to convert it but I'm getting an error:
tried this:
$update_data = $db->update("users", `featured`, [
'AND'=>[ `start_date` => '2022-08-10', `stop_date` => '2022-08-14'] ? [`featured` => '1'] : [`featured` => '0']
]);

PDO is inserting "null" for empty values

I am using PDO for writing to sqlite database.
// $dbo is an instance of PDO
$query = "INSERT INTO items (id, name, rank) VALUES (:id, :name, :rank)";
$statement = $dbo->prepare($query);
$values = array('id' => 1, 'name' => 'Some Name', 'rank' => '');
$statement->execute($values);
$values = array('id' => 1, 'name' => 'Some Name', 'rank' => NULL);
$statement->execute($values);
After executing any of these, I expect "rank" to be an empty string or even a NULL is acceptable.
But what I get in the database is 'null', yes a string 'null' value, not the real NULL.
Could not find any solution after several attempts.
Try sending NULL directly in this line
$values = array('id' => 1, 'name' => 'Some Name', 'rank' => NULL);

How to use query results as conditional in PHP?

I have the following SELECT query that looks to if there are records that meet the given criteria:
$stmt = $conn->prepare(' SELECT (`Active`)
FROM `Table1`
WHERE `Name` = ":name" AND Active <> Yes ');
$stmt->execute([
'name' => $_POST['name']
]);
If results of Active could either be a No or just no results. If the results are a No then the following query should run:
$stmt = $conn->prepare('UPDATE `Table1`
SET `active` = `Yes`
WHERE `Name` = `:name`');
$stmt->execute([
'name' => $_POST['name']
]);
If the results of the SELECT query does not find anything then the following query should run:
$stmt = $conn->prepare(' INSERT INTO `Table1` (`Name`,`Active`)
VALUES (:name, :active ) ');
$stmt->execute([
'name' => $_POST['name'],
'active' => $_POST['active']
]);
How can this conditional be written?
I specifically do not want to set a unique constraint to the name column and create stored procedures I need it to be done as a conditional described above.
This should work..
$stmt = $conn->prepare(' SELECT (`Active`)
FROM `Table1`
WHERE `Name` = ":name" AND Active <> Yes ');
$stmt->execute([
'name' => $_POST['name']
]);
if ($stmt->rowCount() === 0) {
$stmt = $conn->prepare(' INSERT INTO `Table1` (`Name`,`Active`)
VALUES (:name, :active ) ');
$stmt->execute([
'name' => $_POST['name'],
'active' => $_POST['active']
]);
} else {
$stmt = $conn->prepare('UPDATE `Table1`
SET `active` = `Yes`
WHERE `Name` = `:name`');
$stmt->execute([
'name' => $_POST['name']
]);
}
I have not tried this one out but it should work. Tell me if it doesnt.

Sqlite Call to a member function bindParam() on boolean

Hello I try with PDO to insert data to Sqlite, i have tried many ways, but I always get following errors: Call to a member function bindParam() on boolean.
I see also the bindParam() or bindValue return false if an error exist. But I don't find an error.
thx in advance
function insertCostumers(){
$costumers = 'INSERT IGNORE INTO costumers(first_name,last_name,age)
VALUES(:first_name,:last_name,:age)';
$stmt = $this->pdo->prepare($costumers);
$data = [['firstName' => 'Hans',
'lastName' => 'Meier',
'age' => 32],
['firstName' => 'Anna',
'lastName' => 'Mueller',
'age' => 35],
['firstName' => 'Steffi',
'lastName' => 'Gygax',
'age' => 67]];
$stmt->bindParam(
':first_name', $firstName,
':last_name', $lastName,
'age', $age);
foreach ($data as $d) {
// Set values to bound variables
$firstName = $d['firstName'];
$lastName = $d['lastName'];
$age = $d['age'];
// Execute statement
$stmt->execute();
}
die('hello');
}
require "SQLiteConnection.php";
require "SQLiteCreateTable.php";
$sqlite = new SQLiteCreateTable((new SQLiteConnection())->connect());
// create new tables
$sqlite->createTables();
$sqlite->insertCostumers();
$tables = $sqlite->getOrderList();
require "index.view.php";
#SebastianBrosch Thats the Create Statement.
public function createTables() {
$commands = ['CREATE TABLE IF NOT EXISTS costumers (
costumer_id integer PRIMARY KEY,
first_name text NOT NULL,
last_name text NOT NULL,
age integer NOT NULL
)',
'CREATE TABLE IF NOT EXISTS orders (
order_id integer PRIMARY KEY,
order_nr integer NOT NULL,
costumer_id integer,
FOREIGN KEY (costumer_id) REFERENCES costumers (costumer_id)
ON DELETE CASCADE ON UPDATE NO ACTION)'];
// execute the sql commands to create new tables
foreach ($commands as $command) {
$this->pdo->exec($command);
}
}
The variable $stmt is not a PDOStatement object. It is a boolean value (in this case false).
Your INSERT statement is not valid. Try the following instead (missing OR):
$costumers = 'INSERT OR IGNORE INTO costumers(first_name, last_name, age)
VALUES(:first_name, :last_name, :age)';
You can use the methods PDO::errorInfo and PDO::errorCode to get further information.
$costumers = 'INSERT OR IGNORE INTO costumers(first_name,last_name,age)
VALUES(:first_name,:last_name,:age)';
$stmt = $this->pdo->prepare($costumers);
if ($stmt === false) {
echo $this->pdo->errorCode().': '.$this->pdo->errorInfo();
}
You also use $firstName and $lastName before init:
function insertCostumers() {
$costumers = 'INSERT OR IGNORE INTO costumers(first_name, last_name, age)
VALUES(:first_name, :last_name, :age)';
$stmt = $this->pdo->prepare($costumers);
$data = [['firstName' => 'Hans',
'lastName' => 'Meier',
'age' => 32],
['firstName' => 'Anna',
'lastName' => 'Mueller',
'age' => 35],
['firstName' => 'Steffi',
'lastName' => 'Gygax',
'age' => 67]];
foreach ($data as $d) {
$firstName = $d['firstName'];
$lastName = $d['lastName'];
$age = $d['age'];
$stmt->bindParam(':first_name', $firstName, PDO::PARAM_STR);
$stmt->bindParam(':last_name', $lastName, PDO::PARAM_STR);
$stmt->bindParam(':age', $age, PDO::PARAM_INT);
$stmt->execute();
}
}
To make sure the combination of first_name and last_name is unique, you need to add a UNIQUE constraint to your table costumers. Use the following CREATE TABLE statement:
CREATE TABLE IF NOT EXISTS costumers (
costumer_id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
age INTEGER NOT NULL,
UNIQUE (first_name, last_name)
);
You can see the difference with and without the UNIQUE constraint on these following demo:
http://sqlfiddle.com/#!7/79b1c/1/1

Weird error when using MySQL when using PDO

I encountered a very strange bug today. I am getting sideblinded by this so bad as it's breaking my entire application.
So, I have this little framework that I've built where I have a standard modell, so snippeting this will be a little long and descriptive.
<?php include('inc/inc.php'); ?>
<?php
if(!empty($_POST['answer']) && !empty($_POST['levelstart'])){
if($stmt = $site->answerQuestion($_POST['levelstart'], $_POST['answer'])){
if($stmt[0]){
echo json_encode(array('success' => true, 'correct' => $stmt[1], 'correctanswer' => $stmt[2], 'round_end' => $stmt[3]));
}else{
echo json_encode(array('success' => false, 'error' => 'error occurred'.$stmt[1]));
}
}else{
echo json_encode(array('sucess' => false, 'error' => 'Unknown error'));
}
}else{
echo json_encode(array('success' => false, 'error' => 'Provide all necessary parameters.'));
}
?>
this piece of code outputs the following.
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '', '1', '1', '905'){"success":false,"error":"error occurred23000"}
The generated query above is only a dummy one that i simple put together so I don't need the parameterization for simply testing. The "error" key in the json array contains error data, and the errorcode is dumped there.
23000 is the mysql error code for there being a duplicate unique column, but there is no unique column that I'm using in the query(see table struct below.)
Since the function answerQuestion is a very long one, I'll only paste the related lines next. In $site->answerQuestion it calls a function called "insertLevelStarts" which is supposed to insert an entry to the db.
This is how i call it:
if($stmtss = $this->db->insertLevelStarts($_SESSION['user']['id'], $stmts['return'][0]['id'], time(), $roundid, 1, 1, $levelstart)){
And this is how it's declared, also the rest of the related and unknown code:
public function insertLevelStarts($user_id, $question_id, $time, $round_id, $type = 0, $success = 0, $refid = 0){
/*
Type=0 start 1 stop
success=0 for start 1 if successfull on stop
*/
$query = 'INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES (:user_id, :question_id, :time, :round_id, :type, :success, :refid)';
echo $this->genFakeQuery($query, array(
':user_id' => $user_id,
':question_id' => $question_id,
':time' => $time,
':type' => $type,
':success' => $success,
':refid' => $refid,
':round_id' => $round_id
));
return $this->execInsert($query, array(
':user_id' => $user_id,
':question_id' => $question_id,
':time' => $time,
':type' => $type,
':success' => $success,
':refid' => $refid,
':round_id' => $round_id
)
);
}
public function genFakeQuery($query, $array){
foreach($array as $key => $val){
$query = str_replace($key, "'$val'", $query);
}
return $query;
}
public function execUpdate($query, $preparray, $updatearr){
try {
$stmt = $this->db->prepare($query);
$stmt->execute(array_merge($preparray, $updatearr));
$rows = $stmt->rowCount();
if($rows > 0){
return array('type' => 'rowsaffected', 'return' => $rows);
}else{
return array('type' => 'noreturn', 'return' => 'none');
}
} catch(PDOException $ex) {
return array('type' => 'error', 'return' => $ex);
}
}
public function updateClause($query, $update, $updatearr){
if(count($update) > 0){
$count = 0;
foreach($update as $k => $v){
if($count > 0){
$query .= ',';
}
$query .= " `$k` = :$k";
$updatearr[":$k"] = $v;
$count++;
}
}
return array('query' => $query, 'updatearr' => $updatearr);
}
The aforementioned query
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '', '1', '1', '905')
inserts into a table looking like this:
CREATE TABLE IF NOT EXISTS `quiz_level_starts` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`question_id` int(11) NOT NULL,
`time` int(11) NOT NULL,
`type` int(11) NOT NULL,
`success` int(11) NOT NULL,
`ref_id` int(11) NOT NULL,
`round_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `quiz_level_starts`
ADD PRIMARY KEY (`id`);
ALTER TABLE `quiz_level_starts`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Will greatly appriciate any help recieved.
I assume that the error occurs because round_id is an integer field that can not be NULL and has no default value and you pass it an empty value.
Try if this query works:
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '0', '1', '1', '905')

Categories