SQL Server:在 EXEC 中执行动态/内联 sql 表名称并将几何图形作为几何参数传递

发布于 2024-12-27 19:14:17 字数 1461 浏览 4 评论 0原文

我正在尝试在存储过程中执行内联 SQL 语句。我正在使用 SQL Server 2008。

问题是我无法执行第一个内联语句(带有 WHERE 子句)。它崩溃是因为 EXEC(...) 中的字符串是动态创建的,并且所有连接的变量必须是 varchar 类型。

调用过程时出现错误:

在上下文中指定的非布尔类型表达式,其中 预计情况会接近“订单”。

该过程如下所示:

CREATE PROCEDURE loadMyRows
  @table_name    nvarchar(50),
  @bounding_box  varchar(8000)
AS
BEGIN
  -- *********************************** COMMENT *********************************
  -- ** This two code lines are correct and will return true (1) or false (0),  **
  -- ** but they doesn't work within inline EXEC(...)                           **
  --DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);
  --select TOP(5) wkt.STWithin(@bb) AS 'bool'
  -- *********************************** COMMENT *********************************

IF @bounding_box <> ''
BEGIN
    DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);

    EXEC(   
        'SELECT TOP (' + @row_limit + ') * ' +
        'FROM ' + @real_table_name + ' ' +
        'WHERE wkt.STWithin('+@bb+') ' + -- <-- doesn't work :-(
      -- 'WHERE wkt.STWithin(geometry::STGeomFromText('''+@bounding_box+''', 4326)) ' +
      -- ^^ doesn't work, too :-(
        'ORDER BY id ASC '
    );
END
ELSE
BEGIN
    EXEC(
        'SELECT TOP (' + @row_limit + ') * ' +
        'FROM ' + @real_table_name + ' ' +
        'ORDER BY id ASC'
    );
END
END

I'm trying to execute an inline SQL statement within a stored procedure. I'm working with SQL Server 2008.

The problem is that I can't execute the first inline statement (with WHERE clause). It crashes because the string within EXEC(...) is dynamically created and all concatenated variables must be of type varchar.

Error that appears when calling procedure:

An expression of non-boolean type specified in a context where a
condition is expected, near 'ORDER'.

The procedure looks like:

CREATE PROCEDURE loadMyRows
  @table_name    nvarchar(50),
  @bounding_box  varchar(8000)
AS
BEGIN
  -- *********************************** COMMENT *********************************
  -- ** This two code lines are correct and will return true (1) or false (0),  **
  -- ** but they doesn't work within inline EXEC(...)                           **
  --DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);
  --select TOP(5) wkt.STWithin(@bb) AS 'bool'
  -- *********************************** COMMENT *********************************

IF @bounding_box <> ''
BEGIN
    DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);

    EXEC(   
        'SELECT TOP (' + @row_limit + ') * ' +
        'FROM ' + @real_table_name + ' ' +
        'WHERE wkt.STWithin('+@bb+') ' + -- <-- doesn't work :-(
      -- 'WHERE wkt.STWithin(geometry::STGeomFromText('''+@bounding_box+''', 4326)) ' +
      -- ^^ doesn't work, too :-(
        'ORDER BY id ASC '
    );
END
ELSE
BEGIN
    EXEC(
        'SELECT TOP (' + @row_limit + ') * ' +
        'FROM ' + @real_table_name + ' ' +
        'ORDER BY id ASC'
    );
END
END

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

平安喜乐 2025-01-03 19:14:17

我已经找到了解决这个问题的有效方法。 MSDN 向我展示的方式是 http://msdn.microsoft.com/en- US/library/ms175170.aspx。里面写着:

[...] 字符串作为其独立的批处理执行。

这让我知道,如果我想使用表变量作为字符串执行动态语句,这与我在没有 EXECUTE 命令的情况下执行查询相同,例如:

SELECT TOP(@row_limit) *
FROM @real_table_name
WHERE ...
ORDER BY id ASC;

这可能不适用于表名。

所以,如果我改为:

DECLARE @sql_statement nvarchar(MAX) = 'SELECT TOP(@limit) * 
                                        FROM ' + @real_table_name + ' 
                                        ORDER BY id ASC';

-- declaration of parameters for above sql                              
DECLARE @sql_param_def nvarchar(MAX) = '@limit int';

EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit;

那么,这就会起作用。这是因为我将 @sql_statement 简单地定义为一个串联字符串,它将在运行时将动态表名称解析为具有实际现有表名称的字符串。 @limit 参数未受影响,仍然是一个参数。

如果我们随后执行该批处理,我们只需传递 @limit 参数的值,它就可以工作了!

对于几何参数,它以相同的方式工作:

DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);
SET @sql_statement = 'SELECT TOP(@limit) * 
                      FROM ' + @real_table_name + ' 
                      WHERE wkt.STWithin(@geobb) = 1 
                      ORDER BY id ASC';
-- NOTE: This ' = 1' must be set to avoid my above described error (STWithin doesn't return a BOOLEAN!!)

-- declaration of parameters for above sql
SET @sql_param_def = '@limit int, @geobb geometry';

EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit, @geobb = @bb;

希望这很清楚;-)

I've found a working solution for this problem. The way the MSDN showed me was http://msdn.microsoft.com/en-US/library/ms175170.aspx. There's written:

[...] the string is executed as its own self-contained batch.

That let me know, if I want to execute a dynamic statement with a table variable as string, it's the same as I would execute the query without the EXECUTE command, like:

SELECT TOP(@row_limit) *
FROM @real_table_name
WHERE ...
ORDER BY id ASC;

And this would probably not work for the table name.

So, if I write instead:

DECLARE @sql_statement nvarchar(MAX) = 'SELECT TOP(@limit) * 
                                        FROM ' + @real_table_name + ' 
                                        ORDER BY id ASC';

-- declaration of parameters for above sql                              
DECLARE @sql_param_def nvarchar(MAX) = '@limit int';

EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit;

Then, this would work. This is because I define the @sql_statement simply as a concatenated string which will just resolve the dynamic table name at runtime to a string with the name of the real existing table. The @limit parameter is untouched and is still a parameter.

If we then execute the batch we only must pass a value for the @limit parameter and it works!

For the geometry parameter it works in the same way:

DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);
SET @sql_statement = 'SELECT TOP(@limit) * 
                      FROM ' + @real_table_name + ' 
                      WHERE wkt.STWithin(@geobb) = 1 
                      ORDER BY id ASC';
-- NOTE: This ' = 1' must be set to avoid my above described error (STWithin doesn't return a BOOLEAN!!)

-- declaration of parameters for above sql
SET @sql_param_def = '@limit int, @geobb geometry';

EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit, @geobb = @bb;

Hope this was clear ;-)

恋你朝朝暮暮 2025-01-03 19:14:17
create proc usp_insert_Proc_Into_temp
@tempTable nvarchar(10) output
as
begin

 set @tempTable = '##temp' 
 declare @query nvarchar(200)
 --Select statement
 set @query = 'select  1 as A,2 as B, 3 as C into'+ ' '+@tempTable+''
 exec(@query)


end

go


declare @tempTable nvarchar(10)
exec usp_insert_Proc_Into_temp @tempTable output
exec('select *  from' + ' '+ @tempTable+'')

exec ('drop table'+ ' '+@tempTable+'')
create proc usp_insert_Proc_Into_temp
@tempTable nvarchar(10) output
as
begin

 set @tempTable = '##temp' 
 declare @query nvarchar(200)
 --Select statement
 set @query = 'select  1 as A,2 as B, 3 as C into'+ ' '+@tempTable+''
 exec(@query)


end

go


declare @tempTable nvarchar(10)
exec usp_insert_Proc_Into_temp @tempTable output
exec('select *  from' + ' '+ @tempTable+'')

exec ('drop table'+ ' '+@tempTable+'')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文