关于sqlserver临时表的问题,请教高手!

现在在做一个项目,用到的功能是这样的!每个表都有触发器,在更新,追加的时候,会给记录的登陆用户,登陆机器名这两个字段设定值!这两个值是在触发器中从本地临时表中取到的!而临... 现在在做一个项目,用到的功能是这样的!
每个表都有触发器,在更新,追加的时候,会给记录的登陆用户,登陆机器名这两个字段设定值!这两个值是在触发器中从本地临时表中取到的!
而临时表是在应用程序中创建的,因为sqlserver的本地临时表是根据会话来的,会话结束了,这个临时表就被删除掉了,所以在应用程序中,使用ExcuteNoQuery()创建临时表时(在存储过程中创建也一样 执行EXEC后会话结束),会话就结束了,临时表就被删除了,
这时更新数据库数据库数据,触发触发器触发时根本找不到之前创建的临时表了,所以不能正确设定登陆用户,登陆机器名了!
如果用全局临时表的话,又怕有并发问题,
有没有高手知道有什么设定或是别的解决办法,请指教啊!
谢谢各位了,问题已经解决,特回来跟大家分享下解决方案!

罪魁祸首是 在做临时表时使用了sql参数(SqlParameter),
把参数以拼字符串的形式穿进去,
ExcuteNoQuery()执行完不会结束会话,不会删除临时表!

这是在国外网站找到了提示,才解决了这个问题,希望对以后遇到相同问题的人能有帮助!
展开
 我来答
紫仑天玑
2013-08-12 · 萝卜数学关注思维过程
紫仑天玑
采纳数:324 获赞数:888

向TA提问 私信TA
展开全部

回头你补上一万分吧!还不起就等几年你水平够了进我团队打工偿还。(*^__^*) ……

第一:都不用看,你们就把设计概要给理解错了。

以上只是一些较为简单的实现方式。所以更新登录名等信息用触发器根本就是劣质的。

当下普遍用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];


以上只是样例,实际都是自己制定主键方式的。

更多追问追答
追问
谢谢啊!
再顺便问一下!
这个不会有多用户并发问题吗?
追答
并发是个多线程程序都会有的,
而你这个只要保证存储的是最新的信息就可以认为是正确的。
本身你们项目的实现方案已经通盘是个错误了。

一般保证在同一个事务下运行,设置隔离级别基本可以保证原子操作,但是中间有一个触发器,
根本不可能保证是原子操作。

其实最后那个表还有一列是自增标识,从而实现最新版本信息,而没有采用时间。
万山数据
2024-11-14 广告
数据仓库处理是北京万山数据科技有限公司的核心业务之一。我们专注于高效、安全地处理大规模数据,通过先进的数据仓库技术,实现数据的集成、存储、管理和分析。我们的数据仓库解决方案能够支持复杂的数据查询和分析需求,提供实时的数据洞察,助力企业做出更... 点击进入详情页
本回答由万山数据提供
szm341
2013-08-12 · TA获得超过6726个赞
知道大有可为答主
回答量:5005
采纳率:100%
帮助的人:5163万
展开全部
string strsql = "select @userid,@userNm into #pro_set";
//执行创建临时表的sql
com.ExecuteNonQuery();
//这里调用了一个更新或追加的sql
---》
string strsql = "select @userid,@userNm into #pro_set";
这里拼接哪个调用更新或追加的sql,使其与该临时表保持在同一个会话当中
com.ExecuteNonQuery();
更多追问追答
追问
谢谢回答!
首先创建临时表是在共通方法中实现的
用更新或追加的sql是在具体的业务中实现的,把他们合到一起的工作量会很大,这不是个小项目,几百人月。
追答
那我只能建议你们改用实体表了,把这个临时表创建填充的操作改为实体表的插入
然后跟一个自增的版本号,用ExecuteScalar()返回
在要操作的表中新增一个记录版本号的字段,触发时根据这个值在触发器中操作
本回答被提问者和网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
下扬州啊
2013-08-12 · TA获得超过2519个赞
知道大有可为答主
回答量:4870
采纳率:40%
帮助的人:2127万
展开全部
那就在EXEC之前做,不再触发器里面做
更多追问追答
追问
谢谢回答!

创建临时表的方法是基类的方法,每个开启事物时,都会去执行的,增删改查是在你自己方法中做的,所以按现在的系统是不可能拿到前面做了。
不知到还有没有更好的方法?
追答
你用before insert试试
按理说before insert应该在你的Exec之前
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式