lastInsertId() with UPDATE statement returns 0 when using php7.2 - pdo

I have the following code to update a row in a MariaDB table:
<?php
$statement = <<<SQL
UPDATE `my_table`
SET
`my_name` = :my_name,
`my_id` = LAST_INSERT_ID(my_id)
WHERE `my_id` = :my_id;
SQL;
try {
$sth = $this->dbh->prepare($statement);
$sth->bindValue(':my_name', 'Foo');
$sth->bindValue(':my_id', 12, PDO::PARAM_INT);
$sth->execute();
if ($this->dbh->lastInsertId() == 0) {
echo 'Id not found!';
}
} catch (\PDOException $e) {
echo 'Transaction failed!';
}
The my_id = LAST_INSERT_ID(my_id) part in my SET clause, sets the value of Maria DB's LAST_INSERT_ID() to the value of `my_id` of the updated row.
Executing SELECT LAST_INSERT_ID(); in my sql client confirms the value is set (result = 12).
In php I use PDO::lastInsertId to get this value and if it's 0, a matching row doesn't exist. This way I can make a difference between a 'my_id doesn't exist' error and a silent UPDATE of nothing (and all other transaction errors).
This works fine in PHP 5.6.23/MariaDB 10.1.13, but now I'm at PHP 7.2.11/MariaDB 10.1.36 and the returnvalue of PDO::lastInsertId remains zero while the row is updated indeed.
Did the behavior of PDO::lastInsertId change between this versions?
Is it some kind of bug?
Did the code work accidentally before, but it contains an error or something?
Thank you for your response.
Edit: I can confirm the code still works with PHP v7.1.8

Remove this:
, `my_id` = LAST_INSERT_ID(my_id)
There is no need for it; the WHERE clause is already verifying that it is set.
I can't say whether something changed; but I really think you should change your code.

Related

SQL Redshift - count number of times column A value appears in column B value [duplicate]

I am wanting to count all occurrences of the # symbol in a field and originally i thought LIKE '%#%' would be the way to go, but if the character appears in the field more than once it only counts it as one.
What other method are there that i could use that would count every occurrence?
Thanks.
EDIT
For anyone needing it, this is what i ended up using that works.
$count = 0;
$sql = mysql_query("SELECT LENGTH(field_name) - LENGTH(REPLACE(field_name,'#','')) AS 'occurs' FROM table_name WHERE field_name LIKE '%#%'");
while ($data = mysql_fetch_assoc($sql)) {
$count += $data['occurs'];
}
echo $count;
select length('aa:bb:cc:dd')-length(replace('aa:bb:cc:dd',':',''));
source: http://lists.mysql.com/mysql/215049
You could make this even simpler by using the ``substr_count function in php. see below.
$message = $row['themessage'];
echo substr_count($message, '#');
what this will return is the number of times # has occurred in your "themessage" field in your database.

CDbCommand::createCommand() returns zero affected rows inside migration

This code works just fine (all database items updated as expected):
foreach($idMap as $menuId=>$pageId)
{
$sql = "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
$affectedRows = Yii::app()->db->createCommand($sql)->execute();
echo $affectedRows." affected rows\n";
}
But it prints 0 affected rows for each executed query. Why?
The same effect is, when executing many rows affecting statements in one SQL query:
$sql = '';
foreach($idMap as $menuId=>$pageId)
{
$sql .= "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
}
$affectedRows = Yii::app()->db->createCommand($sql)->execute();
echo $affectedRows." affected rows\n";
What am I missing? Docs says, that CDbCommand::execute should return number of rows affected by the execution. Does this feature work, when used inside migration?
CDbCommand::execute returns the row Count from underlying PDO interface, PDOstatement::rowCount only returns the row count of the last statement.
I had tested this within migration to be sure that migrate script is not running any other commands for cleanup etc, this is not the case, I am able to get correct row values from within and outside migration as well.
The most likely reason you are getting 0 as the value is because of the update command did not affect any rows ( i.e. the link values were already set to the correct values), UPDATE will return 0 if no change has occurred.
Perhaps you already run the migration on your test db and migrated down to test it few more times, however during the subsequent passes no update actually happened.
Note in the second scenario only the count of the last command ( a single row update will be shown even if update changes the table as PDOstatement::rowCount only returns the count for last statement executed.

How to pass $node->nid into update statement

I am trying to update a node in Drupal 7 using the following code.
db_update('table')
->fields(array('column1' => 1))
->condition('entity_id', 2, '=')
->execute();
The statement works as expected: The value of column1 gets updates to 1 where the entity_id = 2.
However, I am trying to replace 2 with the current node.
If I use return $node->nid; then the current node gets returned as expected. If I try to put $node->nid into the query it doesn't validate.
The following code doesn't return anything; the query just fails.
db_update('table')
->fields(array('column1' => 1))
->condition('entity_id', $node->nid, '=')
->execute();
Total stab in the dark here:
try
global $node;
Before the above lines.
Or just assign a variable to Return %node->nid
and put the variable inside where you have $node->nid?

Detecting no results in adodb select query

I'm using ADODB connection in C. The code works more or less fine but I'm getting errors when there is no result for my query and I try to read it. Relevant code:
__object *con, *rec;
con = __object_create("ADODB.Connection");
if(con!=NULL) con->Open("odbc name");
if (con == NULL || con->State==0)
{
return 0;
}
rec= __object_create("ADODB.RecordSet");
sprintf(query, "SELECT SUM(column) FROM table WHERE %s", constraint);
rec->CursorLocation=3;
rec->Open(query, con, 1, 3);
float result = rec->Fields(0); // <- Error here
rec->Close();
__object_delete(rec);
__object_delete(con);
I'm getting error code 80020005 (Type mismatch). The DB column is type float. When there are records that meet the constraint and I get a result everything works fine. But when it matches no records the DB server returns null and I get the error. Fortunately result is set to 0 which is reasonable but I would like to detect this better.
The standard ways (BOF/EOF, Fields->Count, == NULL, ...) all fail. Most code samples I can find are for VB and not C so they are not really helpful.
rec->Fields(0).Value returns a variant, before assigning to the float variable check if the variant represents a VT_NULL which indicates that the data returned is NULL.

SELECT MAX query returns only 1 variable + codeigniter

I use codeigniter and have an issue about SELECT MAX ... I couldnot find any solution at google search...
it looks like it returns only id :/ it's giving error for other columns of table :/
Appreciate helps, thanks!
Model:
function get_default()
{
$this->db->select_max('id');
$query = $this->db->getwhere('gallery', array('cat' => "1"));
if($query->num_rows() > 0) {
return $query->row_array(); //return the row as an associative array
}
}
Controller:
$default_img = $this->blabla_model->get_default();
$data['default_id'] = $default_img['id']; // it returns this
$data['default_name'] = $default_img['gname']; // it gives error for gname although it is at table
To achieve your goal, your desire SQL can look something like:
SELECT *
FROM gallery
WHERE cat = '1'
ORDER BY id
LIMIT 1
And to utilise CodeIgniter database class:
$this->db->select('*');
$this->db->where('cat', '1');
$this->db->order_by('id', 'DESC');
$this->db->limit(1);
$query = $this->db->get('gallery');
That is correct: select_max returns only the value, and no other column. From the specs:
$this->db->select_max('age');
$query = $this->db->get('members');
// Produces: SELECT MAX(age) as age FROM members
You may want to read the value first, and run another query.
For an id, you can also use $id = $this->db->insert_id();
See also: http://www.hostfree.com/user_guide/database/active_record.html#select
CodeIgniter will select * if nothing else is selected. By setting select_max() you are populating the select property and therefore saying you ONLY want that value.
To solve this, just combine select_max() and select():
$this->db->select('somefield, another_field');
$this->db->select_max('age');
or even:
$this->db->select('sometable.*', FALSE);
$this->db->select_max('age');
Should do the trick.
It should be noted that you may of course also utilize your own "custom" sql statements in CodeIgniter, you're not limited to the active record sql functions you've outlined thus far. Another active record function that CodeIgniter provides is $this->db->query(); Which allows you to submit your own SQL queries (including variables) like so:
function foo_bar()
{
$cat = 1;
$limit = 1;
$sql = "
SELECT *
FROM gallery
WHERE cat = $cat
ORDER BY id
LIMIT $limit
";
$data['query'] = $this->db->query($sql);
return $data['query'];
}
Recently I have been utilizing this quite a bit as I've been doing some queries that are difficult (if not annoying or impossible) to pull off with CI's explicit active record functions.
I realize you may know this already, just thought it would help to include for posterity.
2 helpful links are:
http://codeigniter.com/user_guide/database/results.html
http://codeigniter.com/user_guide/database/examples.html