您没有在问题中指定您的数据库产品,但我将从@Pararemter命名样式中猜测您正在使用 SQL Server。
除了将空输入解释为“全部”的特殊要求外,这是对SQL 中的数组问题的重述,由 Erland Sommarskog 彻底探索。阅读他关于该主题的所有文章,以对您可以使用的所有技术进行很好的分析。
在这里,我将解释如何使用表值参数来解决您的问题。
一起执行以下脚本,以幂等方式设置测试环境。
创建示例解决方案
首先创建一个新的空测试数据库StackOverFlow13556628
:
USE master;
GO
IF DB_ID('StackOverFlow13556628') IS NOT NULL
BEGIN
ALTER DATABASE StackOverFlow13556628 SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE StackOverFlow13556628;
END;
GO
CREATE DATABASE StackOverFlow13556628;
GO
USE StackOverFlow13556628;
GO
接下来,创建一个PrinciapalList
包含一列的用户定义表类型principal_id
。此类型包含用于查询系统表的输入值sys.database_principals
。
CREATE TYPE PrincipalList AS TABLE (
principal_id INT NOT NULL PRIMARY KEY
);
GO
之后,创建GetPrincipals
以PrincipalList
表值参数为输入的存储过程,并从sys.database_principals
.
CREATE PROCEDURE GetPrincipals (
@principal_ids PrincipalList READONLY
)
AS
BEGIN
IF EXISTS(SELECT * FROM @principal_ids)
BEGIN
SELECT *
FROM sys.database_principals
WHERE principal_id IN (
SELECT principal_id
FROM @principal_ids
);
END
ELSE
BEGIN
SELECT *
FROM sys.database_principals;
END;
END;
GO
如果表值参数包含行,则该过程将返回sys.database_principals
其中具有匹配principal_id
值的所有行。如果表值参数为空,则返回所有行。
测试解决方案
您可以像这样查询多个主体:
DECLARE @principals PrincipalList;
INSERT INTO @principals (principal_id) VALUES (1);
INSERT INTO @principals (principal_id) VALUES (2);
INSERT INTO @principals (principal_id) VALUES (3);
EXECUTE GetPrincipals
@principal_ids = @principals;
GO
结果:
principal_id name
1 dbo
2 guest
3 INFORMATION_SCHEMA
您可以像这样查询单个主体:
DECLARE @principals PrincipalList;
INSERT INTO @principals (principal_id) VALUES (1);
EXECUTE GetPrincipals
@principal_ids = @principals;
GO
结果:
principal_id name
1 dbo
您可以像这样查询所有主体:
EXECUTE GetPrincipals;
结果:
principal_id name
0 public
1 dbo
2 guest
3 INFORMATION_SCHEMA
4 sys
16384 db_owner
16385 db_accessadmin
16386 db_securityadmin
16387 db_ddladmin
16389 db_backupoperator
16390 db_datareader
16391 db_datawriter
16392 db_denydatareader
16393 db_denydatawriter
评论
此解决方案效率低下,因为您总是必须从表值参数中读取两次。实际上,除非您的表值参数有数百万行,否则它可能不会成为主要瓶颈。
以这种方式使用空表值参数感觉不直观。一个更明显的设计可能只是有两个存储过程——一个返回所有行,一个只返回具有匹配 id 的行。由调用应用程序选择调用哪个应用程序。