I have a relatively simple update query that works fine when I manually execute it from a Mysql Workbench query window, but will not work when I call it as a stored procedure. The stored procedure in question:

CREATE PROCEDURE `sp_UpdateGoal`(
    IN UpdateGoalUserName varchar(45), 
    IN nGoalDate DATE, 
    IN nAmount DECIMAL(9,2), 
    IN nActiveGoal tinyint, 
    IN nOriginalAmount DECIMAL(9,2), 
    IN nChangeLog VarChar(100) 
)
BEGIN
    UPDATE 
        salesgoals
    SET 
        Amount=nAmount,
        OriginalAmount=nOriginalAmount,
        `active`=nActiveGoal,
        ChangeLog=concat(ChangeLog,"\r\n",now()," ",nChangeLog)
    WHERE
        salesgoals.username=UpdateGoalUserName
        AND salesgoals.goalDate=nGoalDate;
END

The call to the stored procedure I'm using:

CALL sp_UpdateGoal( 'lauren', "2020-01-01",150000,1,150000,"Testing sp_UpdateGoal");

which returns Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.

I would prefer not to disable safemode.

The manual query that works:

   UPDATE 
        salesgoals
    SET 
        Amount=150000,
        OriginalAmount=150000,
        `active`=1,
        ChangeLog=concat(ChangeLog,"\r\n",now(),'Testing manual query')
    WHERE
        username='lauren'  
        AND goalDate='2020-01-01';

SalesGoals is a simple table:

CREATE TABLE `salesgoals` (
  `username` varchar(45) NOT NULL,
  `GoalDate` date NOT NULL,
  `Amount` decimal(9,2) NOT NULL,
  `ChangeLog` varchar(500) NOT NULL,
  `Active` tinyint DEFAULT '1',
  `OriginalAmount` decimal(9,2) DEFAULT NULL,
  PRIMARY KEY (`username`,`GoalDate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

It looks to me like when I call the stored procedure, it's ignoring my WHERE clause. I've been staring at this for a crazy long time and don't see anything wrong. What am I missing?

Thanks!

有帮助吗?

解决方案

Right From the MySQL 8.0 Docs

It is possible for UPDATE and DELETE statements to produce an error in safe-updates mode even with a key specified in the WHERE clause, if the optimizer decides not to use the index on the key column:

  • Range access on the index cannot be used if memory usage exceeds that permitted by the range_optimizer_max_mem_size system variable. The optimizer then falls back to a table scan. See Limiting Memory Use for Range Optimization.

  • If key comparisons require type conversion, the index may not be used (see Section 8.3.1, “How MySQL Uses Indexes”). Suppose that an indexed string column c1 is compared to a numeric value using WHERE c1 = 2222. For such comparisons, the string value is converted to a number and the operands are compared numerically (see Section 12.3, “Type Conversion in Expression Evaluation”), preventing use of the index. If safe-updates mode is enabled, an error occurs.

As of MySQL 8.0.13, safe-updates mode also includes these behaviors:

  • EXPLAIN with UPDATE and DELETE statements does not produce safe-updates errors. This enables use of EXPLAIN plus SHOW WARNINGS to see why an index is not used, which can be helpful in cases such as when a range_optimizer_max_mem_size violation or type conversion occurs and the optimizer does not use an index even though a key column was specified in the WHERE clause.

  • When a safe-updates error occurs, the error message includes the first diagnostic that was produced, to provide information about the reason for failure. For example, the message may indicate that the range_optimizer_max_mem_size value was exceeded or type conversion occurred, either of which can preclude use of an index.

  • For multiple-table deletes and updates, an error is produced with safe updates enabled only if any target table uses a table scan.

Based on the these things, you need to run this

select @@global.sql_safe_updates,@@session.sql_safe_updates;

If your output shows 1 for @@global.sql_safe_updates,

  • mysqld process was started up with sql_safe_updates or i-am-a-dummy.
  • Otherwise, it was not started that way.

If your output shows 0 for @@session.sql_safe_updates, that means your client is setting it

  • The client will automatically have @@session.sql_safe_updates set to whatever is in @@global.sql_safe_updates
  • If the client has @@session.sql_safe_updates set to something different from @@global.sql_safe_updates, then the client is personally setting it.

The fact that you can execute it by hand shows that the client program you are using to connect allows you to run the query. You may need to review the setting in MySQL Workbench to see if --safe-updates is being imposed on stored procedure. Other than these things, please check out suggestions from StackOverflow on how to tweek safe-updates off and on in the Workbench.

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top