存储函数中动态 sql 的替代方法
Alternatives to dynamic sql in stored function
我正在编写一个存储函数,用于计算单元格的位置,我需要从 table 中 select 计算该值。为此,我决定将这个位置保存在一个变量中,以便将其用作 LIMIT 子句的偏移量。
根据我的研究,通过 LIMIT 语句将值设置为局部变量的方式是通过准备语句,但我也得到了允许在存储中使用准备语句(也不是任何动态 SQL)职能。有没有其他方法可以解决我的问题?
我的情况的简化示例:
CREATE FUNCTION foo(a int) RETURNS decimal DETERMINISTIC
BEGIN
SET @var1 := (SELECT COUNT(*) FROM table);
SET @var2 := (ROUND(@var1 * a/5))
PREPARE STMT FROM 'RETURN (SELECT * FROM other_table LIMIT ?, ?)';
EXECUTE STMT USING @var2, @var1;
END
$$ DELIMITER ;
理想情况下,这会让我在需要的地方得到我需要的结果。但是,当然,我收到错误代码 1336 说 "Dynamic SQL is not allowed in stored function or trigger"
此存储函数不需要动态 SQL。您不需要为 LIMIT 子句使用动态 SQL。您只需要确保变量是 INT
类型,而不是字符串。
这是一个快速演示:
create function foo(a int) returns int reads sql data
begin
return (select x from test limit 1 offset a);
end
注意其他几件事:
- 使用
READS SQL DATA
而不是 DETERMINISTIC
。您的功能不是确定性的。您应该阅读创建函数的手册页以更好地理解这些选项。
- 不要使用
SELECT *
。一个函数只能 return 一个标量值,而不是一组列。您查询的table实际上可能只有一列,但是让查询更清楚是个好习惯。
- 使用
LIMIT
而不使用 ORDER BY
以后可能会让您感到惊讶,因为它不能保证将使用哪个顺序来确定偏移量。最好明确使用 ORDER BY
。
- 使用
LIMIT
时,我觉得用LIMIT <count> OFFSET <offset>
比LIMIT <offset>, <count>
更清楚。他们做同样的事情,但更容易记住哪个论点是哪个。
- 您的 LIMIT 查询似乎 select 有很多行。您需要查询 select 恰好是一列和一行,否则它对来自存储函数的 return 无效。
我正在编写一个存储函数,用于计算单元格的位置,我需要从 table 中 select 计算该值。为此,我决定将这个位置保存在一个变量中,以便将其用作 LIMIT 子句的偏移量。
根据我的研究,通过 LIMIT 语句将值设置为局部变量的方式是通过准备语句,但我也得到了允许在存储中使用准备语句(也不是任何动态 SQL)职能。有没有其他方法可以解决我的问题?
我的情况的简化示例:
CREATE FUNCTION foo(a int) RETURNS decimal DETERMINISTIC
BEGIN
SET @var1 := (SELECT COUNT(*) FROM table);
SET @var2 := (ROUND(@var1 * a/5))
PREPARE STMT FROM 'RETURN (SELECT * FROM other_table LIMIT ?, ?)';
EXECUTE STMT USING @var2, @var1;
END
$$ DELIMITER ;
理想情况下,这会让我在需要的地方得到我需要的结果。但是,当然,我收到错误代码 1336 说 "Dynamic SQL is not allowed in stored function or trigger"
此存储函数不需要动态 SQL。您不需要为 LIMIT 子句使用动态 SQL。您只需要确保变量是 INT
类型,而不是字符串。
这是一个快速演示:
create function foo(a int) returns int reads sql data
begin
return (select x from test limit 1 offset a);
end
注意其他几件事:
- 使用
READS SQL DATA
而不是DETERMINISTIC
。您的功能不是确定性的。您应该阅读创建函数的手册页以更好地理解这些选项。 - 不要使用
SELECT *
。一个函数只能 return 一个标量值,而不是一组列。您查询的table实际上可能只有一列,但是让查询更清楚是个好习惯。 - 使用
LIMIT
而不使用ORDER BY
以后可能会让您感到惊讶,因为它不能保证将使用哪个顺序来确定偏移量。最好明确使用ORDER BY
。 - 使用
LIMIT
时,我觉得用LIMIT <count> OFFSET <offset>
比LIMIT <offset>, <count>
更清楚。他们做同样的事情,但更容易记住哪个论点是哪个。 - 您的 LIMIT 查询似乎 select 有很多行。您需要查询 select 恰好是一列和一行,否则它对来自存储函数的 return 无效。