Sql server tsql动态表存储过程
我编写了一长串存储过程来更新一些表,当完成时,我意识到大多数存储过程彼此非常相似。。只有很少的字段发生变化 然后我想创建一个存储过程,我就是这么做的:Sql server tsql动态表存储过程,sql-server,tsql,stored-procedures,dynamic,Sql Server,Tsql,Stored Procedures,Dynamic,我编写了一长串存储过程来更新一些表,当完成时,我意识到大多数存储过程彼此非常相似。。只有很少的字段发生变化 然后我想创建一个存储过程,我就是这么做的: CREATE PROCEDURE dbo.Save_All ( @UID nvarchar(100) = NULL, --All @Table nvarchar(40) = NULL, --All @ID int = 0,
CREATE PROCEDURE dbo.Save_All
(
@UID nvarchar(100) = NULL, --All
@Table nvarchar(40) = NULL, --All
@ID int = 0, --All
...
@SubCategory nvarchar(50) = NULL, -- Ticker
@Link nvarchar(300) = NULL -- Ticker
)
AS
SET NOCOUNT ON;
BEGIN
DECLARE @S nvarchar(max)='',
@P nvarchar(max)='',
@cols1 nvarchar(max)='',
@cols2 nvarchar(max)='',
@cols3 nvarchar(max)=''
SELECT @cols1= ISNULL(@cols1 + ',','') + QUOTENAME(name)
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID' Order by colID) AS Columns;
SELECT @cols2= ISNULL(@cols2 + ',','') + '@_' + name
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID' Order by colID) AS Columns;
SELECT @cols3= ISNULL(@cols3 + ',','') + QUOTENAME(name)+'=@_'+ name
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID' Order by colID) AS Columns;
SELECT @cols1 = STUFF(@cols1, 1, 1, '');
SELECT @cols2 = STUFF(@cols2, 1, 1, '');
SELECT @cols3 = STUFF(@cols3, 1, 1, '');
IF (@ID=0 OR @ID is null)
SET @S = N'INSERT INTO @_Table ('+ @cols1 + ') VALUES ('+@cols2+')'
ELSE
SET @S = N' UPDATE @_Table SET ' +@cols3 +' WHERE ID=@_ID'
--PRINT @S
SET @P= '@_UID nvarchar(100),
@_Table nvarchar(40),
@_ID int,
...
@_SubCategory nvarchar(50),
@_Link nvarchar(300)'
EXEC sp_executesql @S,@P,@UID,@Table,@ID,...,@SubCategory,@Link
END
SET NOCOUNT OFF
但是,虽然参数列表很长,但我在示例中修改了大多数参数,但它不包括所有表的所有字段,因此在许多情况下返回错误
解决方案是在@cols1/2/3中只包含定义为参数的字段。。或将相对@_xx设置为空
但这超出了我目前的知识范围
顺便说一下。。存储过程呢?它包含哪些不可接受的错误
谢谢!
乔嗯,我找到了解决办法,比想象的要容易 移动 @P顶部的定义并添加
SET @P= '...'
AND CHARINDEX('@_'+name+' ',@P)>0
在上面加上
SET @P= '...'
AND CHARINDEX('@_'+name+' ',@P)>0
添加到规则以创建3
@cols
总而言之:
CREATE PROCEDURE dbo.Save_All
(
@UID nvarchar(100) = NULL, --All
@Table nvarchar(40) = NULL, --All
@ID int = 0, --All
...
@SubCategory nvarchar(50) = NULL, -- Ticker
@Link nvarchar(300) = NULL -- Ticker
)
AS
SET NOCOUNT ON;
BEGIN
DECLARE @S nvarchar(max)='',
@P nvarchar(max)='',
@cols1 nvarchar(max)='',
@cols2 nvarchar(max)='',
@cols3 nvarchar(max)=''
SET @P= '@_UID nvarchar(100),
@_Table nvarchar(40),
@_ID int,
...
@_SubCategory nvarchar(50),
@_Link nvarchar(300)'
SELECT @cols1= ISNULL(@cols1 + ',','') + QUOTENAME(name)
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID'
AND CHARINDEX('@_'+name+' ',@P)>0 Order by colID) AS Columns;
SELECT @cols2= ISNULL(@cols2 + ',','') + '@_' + name
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID'
AND CHARINDEX('@_'+name+' ',@P)>0Order by colID) AS Columns;
SELECT @cols3= ISNULL(@cols3 + ',','') + QUOTENAME(name)+'=@_'+ name
FROM (SELECT top (100) name FROM sys.columns
WHERE id=OBJECT_ID(@Table) and name<>'ID'
AND CHARINDEX('@_'+name+' ',@P)>0Order by colID) AS Columns;
SELECT @cols1 = STUFF(@cols1, 1, 1, '');
SELECT @cols2 = STUFF(@cols2, 1, 1, '');
SELECT @cols3 = STUFF(@cols3, 1, 1, '');
IF (@ID=0 OR @ID is null)
SET @S = N'INSERT INTO @_Table ('+ @cols1 + ') VALUES ('+@cols2+')'
ELSE
SET @S = N' UPDATE @_Table SET ' +@cols3 +' WHERE ID=@_ID'
--PRINT @S
EXEC sp_executesql @S,@P,@UID,@Table,@ID,...,@SubCategory,@Link
END
SET NOCOUNT OFF
嗯,有点粗糙。。当然有更好的方法建造它,但到目前为止。。看来效果不错
谢谢大家的阅读!
Joe存储过程不应使用sp_uuu前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用sp_u,并使用其他东西作为前缀——或者根本不使用前缀!此外,从SQL Server 2005开始,建议在sys架构中使用系统目录视图(例如sys.columns),而不是旧的、即将弃用的syscolumns视图。请注意。。我马上修改我看不出你在哪里更新身份证?如果ID=@\u ID始终为0,或者我错了,这就没有意义了?@ID是一个输入参数,这是标识列:如果它为0,则将插入,因为不存在0列,如果它大于0,则升级