在存储过程中使用输入参数作为关键字

问题描述 投票:0回答:1

MySQL Workbench用以下错误打我

对象的DDL语句包含语法错误。您必须先修正错误,然后才能修改该对象。

以及提示

“ SELECT”在此服务器版本上的此位置无效,期望:'(',WITH

对于以下代码结构,我试图定义一个过程,该过程接受一个名为time_period的参数,该参数用作SQL时间关键字,例如MINUTEHOURWEEK等,第二个将要乘以该时间段的参数period_count

DELIMITER //
CREATE PROCEDURE getStuffFromPast(
  IN time_period VARCHAR(10),
  IN period_count INT(1)
)
BEGIN
  SELECT * 
  FROM table_A
  INNER JOIN 
    (SELECT x, y, record_date
     FROM table_B
     WHERE (record_date > (NOW() - INTERVAL period_count time_period))
    ) AS B
  ON table_A.x = B.x
    AND table_A.y = B.y;
END//
DELIIMTER ;

我知道这不是定界符问题,因为如果我将代码更改为

DELIMITER //
CREATE PROCEDURE getStuffFromPast(
  IN time_period VARCHAR(10),
  IN period_count INT(1)
)
BEGIN
  SELECT * 
  FROM table_A
  INNER JOIN 
    (SELECT x, y, record_date
     FROM table_B
     WHERE (record_date > (NOW() - INTERVAL period_count HOUR))
    ) AS B
  ON table_A.x = B.x
    AND table_A.y = B.y;
  SELECT time_period;
END//
DELIIMTER ;

我得到正确的第一输出,然后是正确的第二输出。因此,我很确定我的问题是在语法上将输入参数用作过程中的关键字/数据类型。

[如果有一种更优雅的方式来做我想要的事情,请从python客户端调用此过程,如

def execute_sql(query):
   # Handles DB interactions

def get_data_from_past(time_period: str, count: int):
   sql_statement = f'call getStuffFromPast({time_period}, {count})'
   results = execute_sql(sql_statement)

实际上...在键入时,我意识到我们可以将python方法中的time参数转换为我们要在存储过程中处理的基本时间单位;但我仍然想知道在上述存储过程中是否有一种方法可以做我想要的事情。

python mysql python-3.x innodb pymysql
1个回答
1
投票

您的查询基本上可以,但是您必须使用stmt

DELIMITER //
CREATE PROCEDURE getStuffFromPast(
  IN time_period VARCHAR(10),
  IN period_count INT(1)
)
BEGIN
  IF time_period NOT IN   ('MICROSECOND','SECOND','MINUTE','HOUR','DAY'
    ,'WEEK','MONTH','QUARTER','YEARSECOND_MICROSECOND','MINUTE_MICROSECOND'
    ,'MINUTE_SECOND','HOUR_MICROSECOND','HOUR_SECOND','HOUR_MINUTE'
    ,'DAY_MICROSECOND','DAY_SECOND','DAY_MINUTE','DAY_HOUR','YEAR_MONTH') THEN
    SIGNAL SQLSTATE '45000'
      SET MESSAGE_TEXT = 'Time period is not valid';
  END IF;
  SET @sql = 'SELECT * ';
  SET @sql = CONCAT(@sql,'FROM table_A ');
  SET @sql = CONCAT(@sql,'INNER JOIN ');
  SET @sql = CONCAT(@sql,'(SELECT x, y, record_date ');
  SET @sql = CONCAT(@sql,'FROM table_B ');
  SET @sql = CONCAT(@sql,'WHERE (record_date > (NOW() - INTERVAL ',period_count,' ',time_period,')) ');
  SET @sql = CONCAT(@sql,') AS B ');
  SET @sql = CONCAT(@sql,'ON table_A.x = B.x ');
  SET @sql = CONCAT(@sql,'AND table_A.y = B.y;');

  PREPARE stmt from @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
© www.soinside.com 2019 - 2024. All rights reserved.