背景:
SQL Server Management Studio
允许定义自己的查询快捷方式(工具 > 选项 > 环境 > 键盘 > 查询快捷方式
):
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
当表名被引用[my_table]
时也有效。只要对象位于 dbo
(默认)架构中。
问题是,当表具有架构时,它将无法工作:
EXEC dbo.sp_executesql
N'SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(@obj_name)'
,N'@obj_name SYSNAME'
,
执行:
my_schema.my_table
[my_schema].[my_table]
Incorrect syntax near '.'.
当然我可以写:
EXEC dbo.sp_executesql
N'SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(@obj_name)'
,N'@obj_name SYSNAME'
,'
并将其命名为:
[my_schema].[my_table]'
但是额外的 '
也很丑陋且不方便。
问题:
是否可以在中间(位置或什至多个值)传递值到查询快捷方式窗口?
是否可以传递 dostored_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 '.'.
最佳答案
1。是否可以在中间传递值来查询快捷方式窗口?
据我所知,没有解决方法可以实现此目的。
1-b。是否可以传递多个值?
可以使用分隔符对字符串值进行处理,然后将值拆分到另一侧。遗憾的是,没有太多特殊字符来完成这项工作,因为它们几乎都会引发语法错误。然而,“#”可能是一个明智的选择,因为它已经是 tempDB 中临时表的 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。
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 = '#',
@xml = CAST('<X>'+ (REPLACE(@Param1,@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
因此,由于必须将分割字符加倍很不方便,因此最好能够像上面所述那样猜测模式。
关于SQL Server 将标识符传递给存储过程/动态 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38410040/