关于sqlserver临时表的问题,请教高手!
现在在做一个项目,用到的功能是这样的!每个表都有触发器,在更新,追加的时候,会给记录的登陆用户,登陆机器名这两个字段设定值!这两个值是在触发器中从本地临时表中取到的!而临...
现在在做一个项目,用到的功能是这样的!
每个表都有触发器,在更新,追加的时候,会给记录的登陆用户,登陆机器名这两个字段设定值!这两个值是在触发器中从本地临时表中取到的!
而临时表是在应用程序中创建的,因为sqlserver的本地临时表是根据会话来的,会话结束了,这个临时表就被删除掉了,所以在应用程序中,使用ExcuteNoQuery()创建临时表时(在存储过程中创建也一样 执行EXEC后会话结束),会话就结束了,临时表就被删除了,
这时更新数据库数据库数据,触发触发器触发时根本找不到之前创建的临时表了,所以不能正确设定登陆用户,登陆机器名了!
如果用全局临时表的话,又怕有并发问题,
有没有高手知道有什么设定或是别的解决办法,请指教啊!
谢谢各位了,问题已经解决,特回来跟大家分享下解决方案!
罪魁祸首是 在做临时表时使用了sql参数(SqlParameter),
把参数以拼字符串的形式穿进去,
ExcuteNoQuery()执行完不会结束会话,不会删除临时表!
这是在国外网站找到了提示,才解决了这个问题,希望对以后遇到相同问题的人能有帮助! 展开
每个表都有触发器,在更新,追加的时候,会给记录的登陆用户,登陆机器名这两个字段设定值!这两个值是在触发器中从本地临时表中取到的!
而临时表是在应用程序中创建的,因为sqlserver的本地临时表是根据会话来的,会话结束了,这个临时表就被删除掉了,所以在应用程序中,使用ExcuteNoQuery()创建临时表时(在存储过程中创建也一样 执行EXEC后会话结束),会话就结束了,临时表就被删除了,
这时更新数据库数据库数据,触发触发器触发时根本找不到之前创建的临时表了,所以不能正确设定登陆用户,登陆机器名了!
如果用全局临时表的话,又怕有并发问题,
有没有高手知道有什么设定或是别的解决办法,请指教啊!
谢谢各位了,问题已经解决,特回来跟大家分享下解决方案!
罪魁祸首是 在做临时表时使用了sql参数(SqlParameter),
把参数以拼字符串的形式穿进去,
ExcuteNoQuery()执行完不会结束会话,不会删除临时表!
这是在国外网站找到了提示,才解决了这个问题,希望对以后遇到相同问题的人能有帮助! 展开
3个回答
展开全部
回头你补上一万分吧!还不起就等几年你水平够了进我团队打工偿还。(*^__^*) ……
第一:都不用看,你们就把设计概要给理解错了。
以上只是一些较为简单的实现方式。所以更新登录名等信息用触发器根本就是劣质的。
当下普遍用EDM 更新实体的方式,形式较为简洁,基本对更改过的实体进行更新。
如下这个,只是在跨区域跨范围使用。采用了触发器。
USE [EdwinDW]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRI_CU_CashFlow] ON [dbo].[CashFlow] AFTER UPDATE
AS
BEGIN
UPDATE M
SET M.LoginPC=N.LoginPC,
M.LoginName=N.LoginName
FROM [dbo].[CashFlow] M
INNER JOIN
(
SELECT RID,LoginPC,LoginName FROM [dbo].[CU_RLog] A
INNER JOIN
(
SELECT MAX(ID) AS ID FROM [dbo].[CU_RLog] B GROUP BY RID
) C ON(A.ID=C.ID)
) N ON (convert(binary(16),M.%%physloc%%)=N.RID)
INNER JOIN INSERTED F ON(M.CashNo=F.CashNo)
END
DECLARE @CashNo nvarchar(50) set @CashNo='C13081200006'
DECLARE @LoginPC nvarchar(50) set @LoginPC='KROOK'
DECLARE @LoginName nvarchar(50) set @LoginName='KROOK'
------------------------------
--定期删除临时表任务
------------------------------
--模拟所谓的临时表
INSERT INTO [dbo].[CU_RLog]
SELECT
convert(binary(16),A.%%physloc%%),GETDATE(),@LoginPC,@LoginName
FROM [dbo].[CashFlow] A
WHERE A.CashNo=@CashNo
--更新操作
UPDATE [dbo].[CashFlow]
SET CashNo=CashNo
WHERE CashNo=@CashNo
--验证判断
SELECT * FROM [dbo].[CashFlow];
以上只是样例,实际都是自己制定主键方式的。
更多追问追答
追问
谢谢啊!
再顺便问一下!
这个不会有多用户并发问题吗?
追答
并发是个多线程程序都会有的,
而你这个只要保证存储的是最新的信息就可以认为是正确的。
本身你们项目的实现方案已经通盘是个错误了。
一般保证在同一个事务下运行,设置隔离级别基本可以保证原子操作,但是中间有一个触发器,
根本不可能保证是原子操作。
其实最后那个表还有一列是自增标识,从而实现最新版本信息,而没有采用时间。
展开全部
string strsql = "select @userid,@userNm into #pro_set";
//执行创建临时表的sql
com.ExecuteNonQuery();
//这里调用了一个更新或追加的sql
---》
string strsql = "select @userid,@userNm into #pro_set";
这里拼接哪个调用更新或追加的sql,使其与该临时表保持在同一个会话当中
com.ExecuteNonQuery();
//执行创建临时表的sql
com.ExecuteNonQuery();
//这里调用了一个更新或追加的sql
---》
string strsql = "select @userid,@userNm into #pro_set";
这里拼接哪个调用更新或追加的sql,使其与该临时表保持在同一个会话当中
com.ExecuteNonQuery();
更多追问追答
追问
谢谢回答!
首先创建临时表是在共通方法中实现的
用更新或追加的sql是在具体的业务中实现的,把他们合到一起的工作量会很大,这不是个小项目,几百人月。
追答
那我只能建议你们改用实体表了,把这个临时表创建填充的操作改为实体表的插入
然后跟一个自增的版本号,用ExecuteScalar()返回
在要操作的表中新增一个记录版本号的字段,触发时根据这个值在触发器中操作
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
那就在EXEC之前做,不再触发器里面做
更多追问追答
追问
谢谢回答!
创建临时表的方法是基类的方法,每个开启事物时,都会去执行的,增删改查是在你自己方法中做的,所以按现在的系统是不可能拿到前面做了。
不知到还有没有更好的方法?
追答
你用before insert试试
按理说before insert应该在你的Exec之前
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询