谁敢挑战这个问题?

zzc2006 2006-08-03 11:31:24
大家都知道,存储过程用起来很爽,但其有个缺点,通用性还是不够,如一个插入过程,对不同的表需要建立不同的插入过程。如果能够针对每一种操作建立一个存储过程岂不更爽。小弟目前还没有找到思路,有人感挑战一下吗?
...全文
230 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
luoqun_ncs 2006-08-03
  • 打赏
  • 举报
回复
贴一个自动生成triger的代码,供参考

DECLARE @execute BIT
SET @execute = 0

DECLARE @tableName VARCHAR(255), @trigerName VARCHAR(255)
DECLARE @columnName VARCHAR(255), @columnType VARCHAR(255)
DECLARE @trigerScript VARCHAR(8000)
DECLARE @auditColumnsScript VARCHAR(8000)

DECLARE tableCursor CURSOR FOR
SELECT NAME TABLE_NAME
FROM SYSOBJECTS
WHERE LEFT(NAME, 2) = 'T_' AND NAME NOT IN('') AND (NAME LIKE '%MAP' OR NAME IN ('T_CMIS_CODE'))

OPEN tableCursor
FETCH NEXT FROM tableCursor into @tableName
WHILE @@FETCH_STATUS = 0
BEGIN

-- Generate the column list: Begin
DECLARE columnCursor CURSOR FOR
SELECT C.NAME COLUMN_NAME, T.NAME COLUMN_TYPE
FROM SYSOBJECTS O, SYSCOLUMNS C, SYSTYPES T
WHERE O.NAME = @tableName AND O.ID = C.ID AND C.XUSERTYPE = T.XUSERTYPE AND T.NAME <> 'varbinary'

OPEN columnCursor
SET @auditColumnsScript = ''
FETCH NEXT FROM columnCursor INTO @columnName, @columnType
WHILE @@FETCH_STATUS = 0
BEGIN
SET @auditColumnsScript = @auditColumnsScript + '''' + @columnName + ' ='' + CONVERT(VARCHAR, ISNULL(' + @columnName + ','''')) + '','' + '
FETCH NEXT FROM columnCursor INTO @columnName, @columnType
END

SET @auditColumnsScript = LEFT(@auditColumnsScript, LEN(@auditColumnsScript) - 8)

CLOSE columnCursor
DEALLOCATE columnCursor
-- Generate the column list: End

SET @trigerName = 'TR' + RIGHT(@tableName, LEN(@tableName)-1)
SET @trigerScript = '
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = ''' + @trigerName + ''' AND TYPE = ''TR'') DROP TRIGGER ' + @trigerName

IF @execute = 1 EXEC (@trigerScript)

PRINT @trigerScript
PRINT 'GO'

SET @trigerScript = '
/*
Module : CMIS II
Author : Auto Generater
Date : 03/03/2006
Desc :
Output :
-----------------------------------------------------
Date Author Remark
*/
CREATE TRIGGER ' + @trigerName +'
ON ' + @tableName + '
AFTER INSERT, UPDATE, DELETE
NOT FOR REPLICATION
AS
DECLARE @v_UserID VARCHAR(255),
@v_TableName VARCHAR(255),
@v_Action VARCHAR(1),
@v_PreviousValue VARCHAR(1000),
@v_NewValue VARCHAR(1000),
@v_InsertedRowCount INT,
@v_DeletedRowCount INT

SET @v_TableName=''' + @tableName + '''

SELECT @v_InsertedRowCount = Count(*) FROM INSERTED
SELECT @v_DeletedRowCount = Count(*) FROM DELETED

IF (@v_InsertedRowCount = 0)
BEGIN
IF (@v_DeletedRowCount = 0)
RETURN -- No record updated to deleted
ELSE
BEGIN -- Delete action
SELECT @v_UserID = LAST_UPDATED_BY, @v_Action = ''D'' FROM DELETED
IF (CHARINDEX('';'', @v_UserID) = 0)
SET @v_UserID = ''UNKNOWN USER''
ELSE
SET @v_UserID = REPLACE(@v_UserID, LEFT(@v_UserID,charindex('';'', @v_UserID)),'''')
SELECT @v_PreviousValue = ' + @auditColumnsScript + ' FROM DELETED
SET @v_PreviousValue = REPLACE(@v_PreviousValue, '';'' + @v_UserID, '''')
END
END
ELSE
BEGIN
IF (@v_DeletedRowCount = 0)
BEGIN -- Insert action
SELECT @v_UserID = CREATED_BY, @v_Action = ''I'' FROM INSERTED
SELECT @v_NewValue = ' + @auditColumnsScript + ' FROM INSERTED
END
ELSE
BEGIN -- Update action
SELECT @v_UserID = LAST_UPDATED_BY, @v_Action=''U'' FROM INSERTED
IF (UPDATE(LAST_UPDATED_BY) AND NOT UPDATE(LAST_UPDATED_DATE) AND CHARINDEX('';'', @v_UserID) > 0)
RETURN -- This update action is prepare the data for delete action
SELECT @v_NewValue = ' + @auditColumnsScript + ' FROM INSERTED
SELECT @v_PreviousValue = ' + @auditColumnsScript + ' FROM DELETED
END
END

EXEC P_CMIS_AUDIT_ADD @v_UserID, @v_TableName, @v_Action, @v_PreviousValue, @v_NewValue'

IF @execute = 1 EXEC (@trigerScript)

PRINT @trigerScript
PRINT 'GO'

FETCH NEXT FROM tableCursor INTO @tableName
END

CLOSE tableCursor
DEALLOCATE tableCursor
zzc2006 2006-08-03
  • 打赏
  • 举报
回复
sql语句既然是结构化的查询语言,就没有道理不能通用。SQL语句的结构也是有规律的,我们只需要考虑如何用函数、模块化的思想来利用它。查询条件很复杂,但我就不认为不能做出应万变的存储过程。微软的标准函数库、类库不都是通用的吗。大家都可以尝试一下,我想一定可以成功的。
luoqun_ncs 2006-08-03
  • 打赏
  • 举报
回复
楼主的问题可以通过自动生成Insert/Update/Delete的存储过程来实现,不同的数据库只要写一个不同的自动生成工具就可以了。

子陌红尘提供的方法只是针对insert空记录,思路不是很通用,如果字段很多就不好实现,而且自己拼sql很容易被注入。
netcup 2006-08-03
  • 打赏
  • 举报
回复
joyceanne(SQL桥)说的是,我也觉得表名都不一样,如何通用,而且程序中各种条件各种情况都会出现,挺复杂的,并且,存储过程本身就是为了实现复杂业务才用的.若完全通用或者一个应用程序只用一两个通用的存储过程,我觉得从道理上也说不过啊.这是个人愚见,期待高人!
joyceanne 2006-08-03
  • 打赏
  • 举报
回复
存储过程也能通用吗?不同的项目难道存储过程会是通用的吗?至少表名都不同拉.
我觉得所谓的通用是局部的.只有在一企业内部或一个项目中,当有一批类似要求的数据操作时,可以用写一个生成存储过程的存储过程供人调用,来提高工作效率.
一句话通用的存储过程是因人而异,没有大众化的存储过程.
zzc2006 2006-08-03
  • 打赏
  • 举报
回复
大家写的时候不妨注释写的详细一些,大家可以方便看懂,利于互相探讨。
zzc2006 2006-08-03
  • 打赏
  • 举报
回复
不错啊,大家都想一下,争取产生一套完美的通用存储过程,是一件很有意义的事情,欢迎大家继续参与。
子陌红尘 2006-08-03
  • 打赏
  • 举报
回复
目的,对任意表(不完善,暂不考虑BLOB及键)执行insert空行操作。


--创建存储过程
create procedure sp_test(@tname varchar(100))
as
begin
declare @name varchar(100),@xtype int,@v varchar(8000),@s varchar(8000)

set @v = 'declare t_cursor cursor for select name,xtype from syscolumns where id=object_id('''+@tname+''')'
exec(@v)

open t_cursor

fetch next from t_cursor into @name,@xtype

select @s = '',@v = ''

while @@fetch_status = 0
begin
set @s = @s + ','+@name
set @v = @v + ','+case when @xtype in(173,175,34,239,99,231,35,165,167) then ''''''
else '0'
end
fetch next from t_cursor into @name,@xtype
end
close t_cursor
deallocate t_cursor

set @s = 'insert into '+@tname+'('+stuff(@s,1,1,'')+') values('+stuff(@v,1,1,'')+')'
exec(@s)
end
go

--创建测试数据表
create table test(id int not null,name varchar(10) not null,dates datetime not null)
go

--执行存储过程对test表插入空行
exec sp_test 'test'

--查看存储过程执行结果
select * from test
/*
id name dates
-- ---- -----------------------
0 1900-01-01 00:00:00.000

*/
--清除测试环境
drop table test
drop procedure sp_test
fiele 2006-08-03
  • 打赏
  • 举报
回复
存储过程少用,移值性不好
十一月猪 2006-08-03
  • 打赏
  • 举报
回复
我想这个有点困难

尤其是通用的 , 因为每个存储过程代表了 , 不同的思路
不同的流程 , 这个比较困难

那种规范的代码 很好做
cookcook 2006-08-03
  • 打赏
  • 举报
回复
不错的思路啊!
wangdehao 2006-08-03
  • 打赏
  • 举报
回复
通过跟效率是有矛盾的,:)

27,581

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧