SQL Server将标识符传递给存储过程/动态SQL

背景:

sql Server Management Studio允许定义自己的查询快捷方式(工具>选项>环境>键盘>查询快捷键):

图片来自:http://social.technet.microsoft.com/wiki/contents/articles/3178.how-to-create-query-shortcuts-in-sql-server-management-studio.aspx

my_schema.my_table
-- highlight it
-- press CTRL + 3 and you will get the number of rows in table

它工作正常,但它以基本形式连接查询(据我所知,只有在结尾).查询

SELECT COUNT(*) FROM my_schema.my_table;

尝试#1

现在我想写一些更具体的东西,例如传递/连接表名到以下查询(这只是例子):

SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(...)

所以当我写入查询快捷方式:

SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID('

我必须使用:

my_schema.my_table')
-- highlight it
-- press CTRL + 3

额外的’)是非常丑陋和不便.

尝试#2:

第二个试验是使用Dynamic-sql

EXEC dbo.sp_executesql
      N'SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(@obj_name)',N'@obj_name SYSNAME',

执行:

my_table
 -- highligt it 
 -- and run

LiveDemo

当表名引用[my_table]时也可以.只要对象处于dbo(认)模式.

问题是当表具有模式时,它将不起作用:

EXEC dbo.sp_executesql
      N'SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(@obj_name)',

执行:

my_schema.my_table
[my_schema].[my_table]

LiveDemo2

Incorrect Syntax near ‘.’.

当然可以写:

EXEC dbo.sp_executesql
      N'SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(@obj_name)','

并称之为:

[my_schema].[my_table]'

但额外的“也是丑陋和不便.

问题:

>可以传递值,查询快捷方式窗口,在中间(位置甚至多于一个值)?
>是否可以通过执行stored_procedure / dynamic-sql限定标识符,而不用’,“包装?

备注:

>我不搜索SSMS的插件
>我不想将object_name包装为“my_schema.my_table”
>我知道有sp_helptext(这只是例子,我搜索方法)
>第一个问题是具体的工具(我知道它),但第二个是关于sql Server.

编辑:

澄清传递标识符到SP而没有“或”:

CREATE TABLE dbo.my_table(col INT);
GO

CREATE PROCEDURE dbo.my_proc
  @a SYSNAME
AS
SELECT *
FROM sys.columns
WHERE [object_id] = OBJECT_ID(@a)
GO

EXEC dbo.my_proc
   @a = my_table;

EXEC dbo.my_proc
   @a = dbo.my_table;
-- Incorrect Syntax near '.'.

LiveDemo3

解决方法

中间有可能传递值,查询快捷方式窗口吗?

据我所知,没有办法解决这个问题.

1-B.是否可以传递多个值?

可以使用分隔符来完成字符串值,然后在另一边分割值.可悲的是,没有太多的特殊功能来完成这项工作,因为他们几乎都会引发语法错误.但是,’#’可能是一个明智的选择,因为它已经是临时表中sql的特殊字符.只要检查你是否还没有使用它的标识符,因为它被sql允许(很难,它被禁止为第一个字符).

这是一个例子:
创建一个存储过程,以将参数接收到一个单个字符串中,并将该字符串拆分成每个参数.

CREATE PROCEDURE sp_PassingMultipleStringValues 
        @Param1 NVARCHAR(MAX)
    AS

    --Here I'm using a XML split,but feel free to use any string split function you already have.
    DECLARE @xml        AS XML,@separator  AS VARCHAR(1)

    SELECT  @separator ='#',@xml = CAST('<X>'+ (REPLACE(@Param1,@separator,'</X><X>') +'</X>') AS XML)

    SELECT N.value('.','VARCHAR(200)') AS value 
    FROM @xml.nodes('X') as T(N)
    --Do whatever is needed with them

然后在此图像上配置您的快捷方式. (注意最后的空格)

结果:

2.是否可以传递到stored_procedure / dynamic-sql限定标识符,“呢?

你有多个具有相同标识符的模式?
因为如果没有,那么在另一边使用sys.schemas来检索它而不是传递它呢?
而不是最终输入不方便的字符,您可以减少输入的内容.

使用检索到的模式,您可以随时为其所需的动态sql执行动态sql.

SELECT @Param1 = REPLACE(REPLACE(@Param1,'[',''),']','')

    SELECT TOP 1 @Param1 = [Schema].name + '.' + @Param1
    FROM     sys.objects AS obj
    JOIN     sys.schemas AS [Schema] ON obj.schema_id = [Schema].schema_id
    WHERE    obj.name = @Param1

    SELECT * 
    FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@Param1)

    DECLARE @Query NVARCHAR(MAX) = 'SELECT TOP 1 * FROM ' + @Param1
    EXEC sp_sqlexec @Query

如果您想要处理具有相同标识符的两个不同模式,那么通过使用答案1-b中解释的方法将模式和标识符作为两个参数来传递仍然是可行的.

一切都在一个例子中

由于这里我们要传递多个标识符并指定其模式,因此需要两个分隔符.

CREATE PROCEDURE sp_MultiArgsWithSchema
    @Param1 NVARCHAR(MAX)
AS

SELECT @Param1 = REPLACE(REPLACE(@Param1,'')

--Here I'm using a XML split,but feel free to use any string split function you already have.
DECLARE @xml            AS XML,@ArgSeparator   AS VARCHAR(2),@SchemaSeparor  AS VARCHAR(1)

SELECT  @ArgSeparator = '##',@SchemaSeparor = '#',@ArgSeparator,'</X><X>') +'</X>') AS XML)

IF OBJECT_ID('tempdb..#QualifiedIdentifiers') IS NOT NULL 
    DROP TABLE #QualifiedIdentifiers;

--While splitting,we are putting back the dot instead of '#' between schema and name of object
SELECT QualifiedIdentifier = REPLACE(N.value('.','VARCHAR(200)'),@SchemaSeparor,'.') 
INTO #QualifiedIdentifiers
FROM @xml.nodes('X') as T(N)

SELECT * FROM #QualifiedIdentifiers

--From here,use what is inside #QualifiedIdentifiers and Dynamic sql if need to achieve what is needed
DECLARE @QualifiedIdentifier    NVARCHAR(500)
WHILE EXISTS(SELECT TOP 1 1 FROM #QualifiedIdentifiers)
BEGIN
    SELECT TOP 1 @QualifiedIdentifier = QualifiedIdentifier
    FROM #QualifiedIdentifiers

    SELECT * 
    FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@QualifiedIdentifier)

    DELETE TOP (1) 
    FROM #QualifiedIdentifiers
    WHERE QualifiedIdentifier = @QualifiedIdentifier
END

用法(请注意,指定模式不是强制性的):

因此,由于不必将分割字符加倍,所以最好是如上所述猜到模式.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...