首页 > 解决方案 > 将 RAW SQL 作为参数传递给函数以检查数据是否存在的问题

问题描述

我无法触摸 VB 代码以使这部分对自己更容易。它由州外的极少数开发人员处理。所以这只是一个 SQL 问题。我知道我可以在 VB 中进行更改(所以不要将其作为解决方案)但是,我们的分析师不能。这是一家价值数十亿美元的公司,像这样的变化将经过严格的批准程序,并且可能会被拒绝。但是,我们可以自由地 [在应用程序中] 制作自定义表/字段并在数据库级别进行编辑。

我的目标是创建一个函数,从前端的字段中获取 RAW SQL 并将其作为参数传递,以证明“打印文档”是否有效。它返回 True 或 False。如果为 True,则打印文档。

示例:脚本:这将采用hmy from property where scode = '26thst'参数中的 SQL。

功能:抓取 SQL,只需要检查 SQL 是否存在并传回 True 或 False

我已经制作了函数并且它是合法的,但似乎没有产生结果。文档被跳过。我对 SQL 的 OOP 过程感到困惑,以在 Execute @SQL 上证明 True/False

CASE 
        WHEN ISNULL(RS1.sdocument1, '') <> '' AND RS1.balwaysprint1 = 'NO'
            AND NYSQLFUNCTION(RS1.SSQL1) = 'TRUE' THEN RS1.RS1.DOCUMENT1            
        WHEN ISNULL(RS1.sdocument1, '') <> '' AND RS1.balwaysprint1 = 'YES'
            THEN RS1.RS1.DOCUMENT1
        END "_FILE_1"

CREATE FUNCTION NYSQLFUNCTION(@SQLTEXT NVARCHAR(MAX))
RETURNS VARCHAR(500)AS BEGIN
DECLARE @FILEPRINT AS VARCHAR(5)
IF EXISTS(SELECT @SQLTEXT) 
SET @FILEPRINT = 'TRUE'
ELSE
SET @FILEPRINT = 'FALSE'
RETURN @FILEPRINT END;

标签: sqlsql-server-2012

解决方案


笔记!当您调用一个函数时,您通常需要包含架构(默认 dbo)......所以dbo.NYSQLFUNCTION

另外......据我所知,该函数将始终返回“TRUE”。如果您想至少检查是否提供了某些 SQL,您可以这样做...

IE:

CREATE FUNCTION NYSQLFUNCTION(@SQLTEXT NVARCHAR(MAX))
RETURNS VARCHAR(500) AS 
BEGIN
  DECLARE @FILEPRINT AS VARCHAR(500)
  IF @SQLTEXT IS NOT NULL AND LEN(@SQLTEXT) > 0  
    SET @FILEPRINT = 'TRUE'
  ELSE
    SET @FILEPRINT = 'FALSE'
  RETURN @FILEPRINT 
END;

如果您确实想要执行提供的 SQL,那么您需要更改函数来执行此操作。

...但您不能调用 sp_executeSQL 从函数中动态执行 SQL(因为它是一个存储过程。有关详细信息,请参阅从函数执行存储过程

所以你可以在上面的答案中做一个可怕的黑客......

或者......您也许可以使用存储过程而不是函数(取决于调用它的代码)

或者......如果您知道查询总是会要求来自同一个表的条目,您可以只解析参数的文本。EG....我假设 SQLTEXT 将始终要求从表“属性”中使用 where 子句的条目scode = 'something'

CREATE FUNCTION NYSQLFUNCTION(@SQLTEXT NVARCHAR(MAX))
RETURNS VARCHAR(500) AS 
BEGIN

  DECLARE @FILEPRINT AS VARCHAR(500) = 'FALSE'

  -- eg.... @SQLTEXT should be something like....  hmy from property where scode = '26thst'
  DECLARE @scode NVARCHAR(500)
  DECLARE @scodeStartIndex INT, @sCodeEndIndex INT
  SELECT @scodeStartIndex = CHARINDEX(' scode ', @SQLTEXT)
  IF @scodeStartIndex > 0 
  BEGIN
    SELECT @scodeStartIndex = CHARINDEX('''', @SQLTEXT, @scodeStartIndex)
    IF @scodeStartIndex > 0
    BEGIN
      SELECT @sCodeEndIndex = CHARINDEX('''', @SQLTEXT, @scodeStartIndex + 1)
      IF @sCodeEndIndex > 0
      BEGIN
        SELECT @scode = SUBSTRING(@SQLTEXT, @scodeStartIndex + 1, @sCodeEndIndex - (@scodeStartIndex + 1))
        IF EXISTS (SELECT NULL FROM [property] WHERE scode = @scode)
        BEGIN
            SELECT @FILEPRINT = 'TRUE'
        END
      END
    END
  END

  RETURN @FILEPRINT 
END;

或者...您可以使用的最后一个选项(取决于您修改数据库的能力)是创建一个 CLR 函数,该函数执行提供的 SQL 查询并返回 true/false。您将能够在用户定义的函数中调用 CLR 函数。这是一篇可能有帮助的文章:https ://www.codeproject.com/Articles/1098543/Use-SQL-CLR-Function-to-Overcome-Limitation-of-SQL


推荐阅读