Eri*_*son 4 sql-server stored-procedures
我正在创建一个存储过程,我希望它接受不同数量的参数,并根据提供的参数数量具有不同的行为。因此,假设我提供一个参数(例如一个数字),它会返回该数字。如果我给它提供两个数字,我希望它把它们加在一起。如果我为它提供一个字符串和一个数字,我希望它将字符串与数字连接起来并显示它——类似于 Java 中重载构造函数的行为。
SQL Server 中的存储过程是否有这样的功能,或者我最好只创建单独的存储过程。我只想走这条路,让我的应用程序结构更简单。
谢谢
<TL;DR>
SQL Server 是否支持重载:不支持。但即使是这样,您也可能会遇到与源代码控制和/或调试相关的问题。
是否可以传入参数的子集,从而改变行为:是的,但是您将拥有一段不容易使用或维护的代码。
结论:只需为每个行为创建一个存储过程或函数。这将是:
关于最终目标如何解释这个问题似乎有些混乱,并且双方都在做出假设,所以让我们首先澄清我们实际上在谈论什么。
超载
重载包括以下全部而不是部分:
代码分离:完全分离的功能/方法。
这些单独的代码段完全相同的函数/方法名称。
输入参数的唯一数量和/或数据类型组合。
共享名称的执行会根据签名(输入参数的唯一变化)路由到正确的函数/方法。
每个具有相同名称但不同输入参数的单独函数/方法可以具有不同的返回值数据类型(注意:这只是一种能力,而不是上述项目的要求)。
考虑到这一点,对于存储过程或函数(标量或 TVF),SQL Server 中的重载是不可能的(在任何程度上)。存储过程和函数必须具有唯一的名称(至少在特定架构内)。但是,此限制仅适用于用户定义的对象,因为很多内置函数都使用重载。
SQL Server 确实有“编号”存储过程(如@Aaron 的回答中所指出的),但这些不应该与重载(甚至不是部分)混淆,因为它们缺少使重载与那些相同的、单独的代码片段不同的所有内容独特的名字:
虽然存储过程的“基本”名称可以相同,但不能使用该基本名称来引用执行代码;您需要包含“数字”(好吧,因为;1它是可选的),这与使用完全不同的名称没有什么不同。意思是,执行该名称而不;<number>跟随名称将始终路由到ProcName;1. 因此,“数字”实际上是名称的一部分。
事实上,唯一可以在不使用;<number>语法的情况下引用组的时间是在DROP PROCEDURE语句中,然后这是引用组的唯一方法。意思是,你不能DROP PROCEDURE ProcName;3,而只能放弃所有这些。
输入参数的变化不需要是唯一的,如下例所示:
CREATE PROCEDURE #NumberedProc (@Input INT)
AS
SELECT @Input AS [inp];
GO
CREATE PROCEDURE #NumberedProc;2 (@Input INT)
AS
SELECT @Input * 2 AS [h], 2 AS [g];
GO
EXEC #NumberedProc 55;
EXEC #NumberedProc;2 55;
Run Code Online (Sandbox Code Playgroud)自动路由到适当的模块是不可用的,因为由于允许签名相同,所以它不可用。因此在执行时需要版本号。
在 PostgreSQL 中允许真正的函数重载,它确实有效,但它也带来了更多的痛苦。从应用层的角度来看,它确实在较小程度上简化了代码,但是很难在源代码管理中进行管理(假设每个对象都有一个以对象名称命名的脚本)以及调试(您有从错误消息中寻找特定的签名)。我们最终消除了重载,并使每个唯一的签名都有一个唯一的对象名称 ;-)。
传入导致不同行为的参数子集
NULL对于存储过程和函数,您可以使用具有默认值(默认值可以是)的可选参数,但这仍然是单个存储过程或函数。意义:
没有代码分离;您将需要一系列IF语句才能正确路由到所需的功能。假设默认值设置为NULL,您将检查哪些输入参数是NOT NULL。
返回类型:
标量函数只能有一种返回数据类型。你可以返回SQL_VARIANT,以避免特定的返回类型,但也有问题,这种方法:性能退化和LOB类型不支持(即VARCHAR(MAX),NVARCHAR(MAX),VARBINARY(MAX)和XML)。
表值函数只能有一种返回类型,它是在编译时确定的。
存储过程确实允许在运行时定义结果集结构,但这对于应用层中的代码来说将是一个非常混乱的界面。
存储过程也允许使用OUTPUT参数,但对于将要返回的每种数据类型,您至少需要一个参数,并且调用代码需要根据传入的输入参数知道要检查哪些参数。这将也是一个令人困惑的代码接口。
因为这是一个单一的对象,所以您没有真正重载时的管理和调试问题,但是您现在拥有一个庞大的、混乱的、令人费解的存储过程或函数,它们也很难维护,只是出于不同的原因。
它会是这样的:
CREATE PROCEDURE dbo.DoTooMuchInOneProcedure
(
@Int1 INT = NULL,
@Int2 INT = NULL,
@String1 NVARCHAR(50) = NULL,
@IntOut INT = NULL OUTPUT,
@StringOut NVARCHAR(50) = NULL OUTPUT
)
AS
SET NOCOUNT ON;
IF (@Int1 IS NOT NULL AND @Int2 IS NULL AND @String1 IS NULL)
BEGIN
SET @IntOut = @Int1;
RETURN;
END;
IF (@Int1 IS NOT NULL AND @Int2 IS NOT NULL)
BEGIN
SET @IntOut = @Int1 + @Int2;
RETURN;
END;
IF (@Int1 IS NOT NULL AND @String1 IS NOT NULL)
BEGIN
SET @StringOut = @String1 + CONVERT(NVARCHAR(50), @Int1);
RETURN;
END;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6768 次 |
| 最近记录: |