"Row cannot be located for updating" error [another] - mysql

I'm working with Delphi (XE3) and need to connect to a MySQL database. I'm having a strange problem that seems quite common but I still haven't entirely solved this problem.
traditional solutions include:
setting "Update Criteria" to adCriteriaKey.
ensure your table has a primary key (and tell the ADO Table about it)
problem 1:
start the application, execute the code: if the new value happens to match what's already in the database, I get the error at position "B".
problem 2:
start the application, execute the code: if the new value happens to be different from what's already in the database, it will execute successfully once and thereafter, give an error at position "A".
there shouldn't be any problem locating the record at anytime since the record primary key has not been changed.
object conMain: TADOConnection
Connected = True
ConnectionString =
'Provider=MSDASQL.1;Password=p;Persist Security Info=True;U' +
'ser ID=M;Extended Properties="Driver={MySQL ODBC 5.3 ANSI Dri' +
'ver};SERVER=yukon;DATABASE=db;UID=M;Pwd=p;PORT=3306;' +
'"'
LoginPrompt = False
Mode = cmShareDenyNone
Left = 48
Top = 24
end
object ADOTable1: TADOTable
Connection = conMain
IndexFieldNames = 'FacilityID'
TableName = 'facility'
Left = 152
Top = 24
end
procedure TForm1.Button1Click(Sender: TObject);
begin
conMain.Open;
ADOTable1.Open;
ADOTable1.Properties.Item['Update Criteria'].Value:=adCriteriaKey;
// **A**
if ADOTable1.Locate('facilityid', '{C0FADCC8-15C9-48C8-8003-3BBD4AB74586}', []) then
begin
ADOTable1.Edit;
ADOTable1.FieldByName('facilityaddress1').AsString:='mickey street';
ADOTable1.Properties.Item['Update Criteria'].Value:=adCriteriaKey;
// **B**
ADOTable1.Post;
end
else
showmessage('not found!');
ADOTable1.Close;
conMain.Close;
end;
it's as though the Post method or the connection left the database in some intermediate state...
here's what the database log says when I demonstrate problem 1.
M#D3400 on db
SET NAMES latin1
SET character_set_results = NULL
SET SQL_AUTO_IS_NULL = 0
select database()
select database()
SHOW GLOBAL STATUS
SELECT ##tx_isolation
set ##sql_select_limit=DEFAULT
select * from facility
SHOW KEYS FROM `facility`
UPDATE `db`.`facility` SET `FacilityAddress1`=? WHERE `facilityid`=?
UPDATE `db`.`facility` SET `FacilityAddress1`='mickey street22' WHERE `facilityid`='{C0FADCC8-15C9-48C8-8003-3BBD4AB74586}'
here's what the database log says when I demonstrate problem 2.
SHOW GLOBAL STATUS
M#D3400 on db
SET NAMES latin1
SET character_set_results = NULL
SET SQL_AUTO_IS_NULL = 0
select database()
select database()
SELECT ##tx_isolation
set ##sql_select_limit=DEFAULT
select * from facility
SHOW KEYS FROM `facility`
UPDATE `db`.`facility` SET `FacilityAddress1`=? WHERE `facilityid`=?
// SUCCESSFUL
UPDATE `db`.`facility` SET `FacilityAddress1`='mickey street22' WHERE `facilityid`='{C0FADCC8-15C9-48C8-8003-3BBD4AB74586}'
SHOW GLOBAL STATUS
SHOW GLOBAL STATUS
SHOW GLOBAL STATUS
db
select * from facility
UPDATE `db`.`facility` SET `FacilityAddress1`=? WHERE `facilityid`=?
// ERROR!
UPDATE `db`.`facility` SET `FacilityAddress1`='mickey street22' WHERE `facilityid`='{C0FADCC8-15C9-48C8-8003-3BBD4AB74586}'
SHOW GLOBAL STATUS
setting the "Update Criteria" in various places was of no help.
reduced the table down to just two fields: facilityid varchar(38), facilityaddress1 varchar(50). same result...

form http://www.connectionstrings.com/mysql-connector-odbc-5-2/, I found:
Provider=MSDASQL;Driver={MySQL ODBC 5.3 UNICODE Driver};Persist Security Info=True;Server=yukon;Database=ocean;User=M;Password=p;Option=2;
"Option=2" is suggested for VB
http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html#codbc-dsn-option-combos
works!
Thank you all for your contributions.

Related

What is the syntax for passing named parameters in MariaDB?

I would expect from here...
https://mariadb.com/kb/en/user-defined-variables/
and here...
https://dev.mysql.com/doc/refman/5.7/en/user-variables.html
that this would work (from python)...
conn.execute("select * from db.`My Table` where `my id` = #my_id",{'#my_id':54321}).fetchall()
but it doesn't. I can get it working using the '%s' syntax, & passing in a list but I'd like named parameters.
Do I have to run
SET #my_id = 54321
first? Do I have to use a stored proc?
As long as it is on the same connection, you can execute SET #my_id = 54321 followed by select * from db.My Table where my id = #my_id. Doing it that way, passing the value as a parameter in the .execute() shouldn't be needed.

Update database record by selected id and reset the initial record

Please how do i update all record to 0 and set only the selected ID to 1
UPDATE address SET default_addr = 1
WHERE addr_id = 100 AND user = 'peter'
The above query will update the selected address to 1 which is good, but i want to set other address or the old selected default to 0 with one query
In MySQL, you can do:
UPDATE address
SET default_addr = (addr_id = 100 AND user = 'peter');
(This shorthand uses the fact that MySQL treats booleans as numbers in a numeric context, with "0" for false and "1" for true.)
If you want only one default address for the user named Peter, then use a where:
UPDATE address
SET default_addr = (addr_id = 100)
WHERE user = 'peter';
I suspect this is the logic that you really want.
use a conditional update using case statement
update address set default_address = case when addr_id = 100 and user = 'peter' then 1 else 0 end
here is a functional example
I built a sample schema. These are often helpful to provide in your future questions.

Calling stored procedure in MySQL takes forever to execute

I have a stored procedure which I'm trying to call, and it takes forever to execute. I have no idea what's wrong. A similar stored procedure in another database executes perfectly. I'm not well-versed with MySQL Workbench, so I don't know if the database settings are different or something.
Following is my stored procedure:
CREATE
DEFINER = `admin`#`%`
PROCEDURE `calculate_daily_coil_moved_by_crane_data`()
BEGIN
set #curr_date = curdate();
set #pre_date = date_add(curdate(), interval -1 day);
set #a_shift_start_ts = concat(#pre_date, ' 06:00:00');
set #a_shift_end_ts = concat(#pre_date, ' 13:59:59');
set #b_shift_start_ts = concat(#pre_date, ' 14:00:00');
set #b_shift_end_ts = concat(#pre_date, ' 21:59:59');
set #c_shift_start_ts = concat(#pre_date, ' 22:00:00');
set #c_shift_end_ts = concat(#curr_date, ' 05:59:59');
SELECT #curr_date,
#pre_date,
#a_shift_start_ts,
#a_shift_end_ts,
#b_shift_start_ts,
#b_shift_end_ts,
#c_shift_start_ts,
#c_shift_end_ts;
#SET DATA
insert into daily_coil_move_by_crane_data_for_report (crane_id, crane_name, date, a_shift, b_shift, c_shift)
select cr.id, cr.name, #pre_date, 0, 0, 0
from yms_phase3.crane cr
where active = 1
order by cr.name;
#----------------------------------------------------------------------------------------------------
#--> COILS MOVED BY CRANE A Shift <--
#----------------------------------------------------------------------------------------------------
SET #shift = 'A';
#FETCH ROW DATA
update daily_coil_move_by_crane_data_for_report
set a_shift = ifnull((select COUNT(*)
FROM yms_phase3.workorder_history in_data
where in_data.crane_id = daily_coil_move_by_crane_data_for_report.crane_id
and current_execution_status IN (6 , 7)
and in_data.pick_ts between #a_shift_start_ts and #a_shift_end_ts
group by in_data.crane_name), 0)
where (a_shift is null or a_shift = 0);
#----------------------------------------------------------------------------------------------------
#--> COILS MOVED BY CRANE B Shift <--
#----------------------------------------------------------------------------------------------------
SET #shift = 'B';
#FETCH ROW DATA
update daily_coil_move_by_crane_data_for_report
set b_shift = ifnull((select COUNT(*)
FROM yms_phase3.workorder_history in_data
where in_data.crane_id = daily_coil_move_by_crane_data_for_report.crane_id
and current_execution_status IN (6 , 7)
and in_data.pick_ts between #b_shift_start_ts and #b_shift_end_ts
group by in_data.crane_name), 0)
where (b_shift is null or b_shift = 0);
#----------------------------------------------------------------------------------------------------
#--> COILS MOVED BY CRANE C Shift <--
#----------------------------------------------------------------------------------------------------
SET #shift = 'C';
#FETCH ROW DATA
update daily_coil_move_by_crane_data_for_report
set c_shift = ifnull((select COUNT(*)
FROM yms_phase3.workorder_history in_data
where in_data.crane_id = daily_coil_move_by_crane_data_for_report.crane_id
and current_execution_status IN (6 , 7)
and in_data.pick_ts between #c_shift_start_ts and #c_shift_end_ts
group by in_data.crane_name), 0)
where (c_shift is null or c_shift = 0);
#----------------------------------------------------------------------------------------------------
#INSERT ALL CRANE ENTRY
insert into daily_coil_move_by_crane_data_for_report (crane_id, crane_name, date, a_shift, b_shift, c_shift)
select -1, 'ALL', #pre_date, SUM(a_shift), sum(b_shift), sum(c_shift)
from daily_coil_move_by_crane_data_for_report
where date = #pre_date
group by date;
#UPDATE TOTAL
update daily_coil_move_by_crane_data_for_report
set total_coils_moved = (a_shift + b_shift + c_shift)
where date = #pre_date;
END
Also tried to execute the query from Java using the following:
jdbcTemplate.execute("CALL calculate_daily_coil_moved_by_crane_data;");
But it gives me the following Exception:
java.sql.SQLException: Lock wait timeout exceeded
Any workaround I can do to solve this?
Please try and edit the configuration file, also search for the same here on stack. There are certain possibilities while checking this out,
Check and edit the config file on Hard drive for MySQL increase the cache capacity and default values as the default values are in KB's the memory allocated is very less and to execute such a big procedure it should at least be some MB.
Increase the connection String timeout, that is by setting up right time in seconds. by default it is 60 seconds, which is very less for executing such a procedure, I think in c# at least we set it to '0' seconds which means that it shall not get timed-out till the query is executed.
If Any left Joins/ inner query please try and check whether the same output is produced in inner joins ? as inner joins are faster than left or right joins.
Add Indexes, have foreign key references properly mapped for faster execution of query.
Hope it works.

mysql update updating all user rows in table

Problem:
I have a mySql stored procedure which runs the following UPDATE:
IF target = 'sup' THEN
UPDATE my_table SET deleted = 1, last_updated = lastUpdate WHERE id = ID AND user_id = accountID;
END IF;
The input parameters are:
(IN ID BIGINT, IN lastUpdate DATETIME, IN target VARCHAR(3), IN accountID BIGINT)
When this sproc is called, mySql updates all of the rows in the table for the user_id and seems to ignore the id in the WHERE clause.
Background:
A mobile app makes an ajax json call to a .NET webservice, which then calls the mySql sproc.
The json call is like:
{"id":["5","6","10"],"lastUpdated":"2014-07-19 22:28:53","target":"sup","accountID":"309"}
At the .net webservice, it converts each id entry to Int64 and sends it to the mySql sproc:
For Each checkedID As String In id
cmd.Parameters.AddWithValue("#ID", CType(checkedID, Int64)).Direction = ParameterDirection.Input
cmd.Parameters.AddWithValue("#lastUpdate", dte).Direction = ParameterDirection.Input
cmd.Parameters.AddWithValue("#target", target).Direction = ParameterDirection.Input
cmd.Parameters.AddWithValue("#accountID", accountID).Direction = ParameterDirection.Input
cmd.ExecuteNonQuery()
cmd.Parameters.Clear()
Next
Research and fix attempts:
Lots of search
Using MySQL Workbench; running the SQL directly correctly updates just the targeted row:
UPDATE my_table SET deleted = 1, last_updated = '1970-01-01 10:10:10' WHERE id = "7" AND user_id = 309;
However, if I call the sproc from within MySQL Workbench, it still updates all of the rows for the targeted user:
CALL `my_sproc`(7, '1990-01-01 10:10:10', 'sup', 309);
I cannot see anything wrong with the sproc, unless I've just looked at it for too long. The mobile app has got close to 100 MySQL sprocs, and this is the only one causing an issue.
I am stumped.
Just adding an explicit reference to the table fixed the issue.
my_table.id

MySQL and GROUP_CONCAT() maximum length

I'm using GROUP_CONCAT() in a MySQL query to convert multiple rows into a single string.
However, the maximum length of the result of this function is 1024 characters.
I'm very well aware that I can change the param group_concat_max_len to increase this limit:
SET SESSION group_concat_max_len = 1000000;
However, on the server I'm using, I can't change any param. Not by using the preceding query and not by editing any configuration file.
So my question is:
Is there any other way to get the output of a multiple row query into a single string?
SET SESSION group_concat_max_len = 1000000;
is a temporary, session-scope, setting. It only applies to the current session You should use it like this.
SET SESSION group_concat_max_len = 1000000;
select group_concat(column) from table group by column
You can do this even in sharing hosting, but when you use an other session, you need to repeat the SET SESSION command.
The correct parameter to set the maximum length is:
SET ##group_concat_max_len = value_numeric;
value_numeric must be > 1024; by default the group_concat_max_len value is 1024.
Include this setting in xampp my.ini configuration file:
[mysqld]
group_concat_max_len = 1000000
Then restart xampp mysql
You can try this
SET GLOBAL group_concat_max_len = 1000000;
The correct syntax is mysql> SET ##global.group_concat_max_len = integer;
If you do not have the privileges to do this on the server where your database resides then use a query like:
mySQL="SET ##session.group_concat_max_len = 10000;"or a different value. Next line:
SET objRS = objConn.Execute(mySQL) your variables may be different.
then
mySQL="SELECT GROUP_CONCAT(......);" etc
I use the last version since I do not have the privileges to change the default value of 1024 globally (using cPanel).
Hope this helps.
The short answer: the setting needs to be setup when the connection to the MySQL server is established. For example, if using MYSQLi / PHP, it will look something like this:
$ myConn = mysqli_init();
$ myConn->options(MYSQLI_INIT_COMMAND, 'SET SESSION group_concat_max_len = 1000000');
Therefore, if you are using a home-brewed framework, well, you need to look for the place in the code when the connection is establish and provide a sensible value.
I am still using Codeigniter 3 on 2020, so in this framework, the code to add is in the application/system/database/drivers/mysqli/mysqli_driver.php, the function is named db_connect();
public function db_connect($persistent = FALSE)
{
// Do we have a socket path?
if ($this->hostname[0] === '/')
{
$hostname = NULL;
$port = NULL;
$socket = $this->hostname;
}
else
{
$hostname = ($persistent === TRUE)
? 'p:'.$this->hostname : $this->hostname;
$port = empty($this->port) ? NULL : $this->port;
$socket = NULL;
}
$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
$this->_mysqli = mysqli_init();
$this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
$this->_mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION group_concat_max_len = 1000000');
...
}
CREATE TABLE some_table (
field1 int(11) NOT NULL AUTO_INCREMENT,
field2 varchar(10) NOT NULL,
field3 varchar(10) NOT NULL,
PRIMARY KEY (`field1`)
);
INSERT INTO `some_table` (field1, field2, field3) VALUES
(1, 'text one', 'foo'),
(2, 'text two', 'bar'),
(3, 'text three', 'data'),
(4, 'text four', 'magic');
This query is a bit strange but it does not need another query to initialize the variable; and it can be embedded in a more complex query.
It returns all the 'field2's separated by a semicolon.
SELECT result
FROM (SELECT #result := '',
(SELECT result
FROM (SELECT #result := CONCAT_WS(';', #result, field2) AS result,
LENGTH(#result) AS blength
FROM some_table
ORDER BY blength DESC
LIMIT 1) AS sub1) AS result) AS sub2;