Create Procedure [dbo].[spGenerateID]
(
@sFieldName NVARCHAR(100),
@sTableName NVARCHAR(100)
)
AS
BEGIN
SELECT ISNULL(MAX(ISNULL(@sFieldName, 0)), 0) + 1 FROM @sTableName
END
在上面的过程中,我提供字段名称和表名称,我想要这个字段的最大数量。为什么这不起作用?我也想要检查这些字段是否为空而不是无效。。此过程必须具有我提供的包含最大数字的字段的返回参数。请帮我修复它。
答案 0 :(得分:3)
如果没有在EXEC语句中包装整个SELECT语句,则不能将字段名和表名作为参数:
EXEC ('select isnull(max(isnull([' + @sFieldName + '],0)),0)+1
from [' + @sTableName + '] ')
答案 1 :(得分:2)
答案 2 :(得分:2)
如果始终将其用于标识列,则可以使用变量
SELECT ISNULL(IDENT_CURRENT(@sTableName),0)+1
否则你需要使用动态SQL(关于SQL注入的常见警告适用。)
另外,我对这背后的原因有点怀疑,除非你不担心任何并发性。
我已将参数类型更改为sysname
,因为这更合适。
CREATE PROCEDURE [dbo].[spGenerateID]
(
@sFieldName sysname,
@sTableName sysname,
@id int output
)
AS
BEGIN
DECLARE @dynsql NVARCHAR(1000)
SET @dynsql = 'select @id =isnull(max([' + @sFieldName + ']),0)+1 from [' + @sTableName + '];'
EXEC sp_executesql @dynsql, N'@id int output', @id OUTPUT
END
使用示例
DECLARE @id int
EXECUTE [dbo].[spGenerateID]
'id'
,'MYTABLE'
,@id OUTPUT
SELECT @id
答案 3 :(得分:0)
1)由于表名的传递方式,这不起作用。
2)您只需要检查ISNULL一次,那里有多余的呼叫。
3)您不必声明输出,只需在执行存储过程时捕获返回值。
如果您尝试生成唯一ID,则这不是最好的方法,因为您可能遇到竞争条件并为其中一个呼叫生成重复的ID。理想情况下,ID已经被声明为IDENTITY列,但是如果你不能这样做,那么最好创建一个只返回ID作为IDENTITY列的特殊表。然后,您可以访问该表以获取最新版本,并确保您将获得唯一ID。
以下是没有冗余IsNull()的存储过程的工作方式。
Create Procedure [dbo].[spGenerateID]
@sFieldName NVARCHAR(100),
@sTableName NVARCHAR(100)
AS
BEGIN
Exec ( 'SELECT max(isnull(' + @sFieldName + ',0))+1 FROM ' + @sTableName)
END