2019年11月4日

关于SQL SERVER的两个备忘



最近在用SQL SERVER做数据的后台自动处理,然后利用Thingworx展现。
这其中碰到两个问题,觉得较有代表性,在此做个备忘。

1. 关于游标内调用其它游标
我之前做过很多项目采用ORACLE数据库,其动态游标、物化视图、数组的功能非常NB,给我留下了深刻的印象。
但是我没想到在使用SQL SERVER游标时却踩到了坑。
SQL SERVER有一个全局变量@@FETCH_STATUS用来表示游标的状态,0表示尚未结束,-1表示已结束。
但是关键@@FETCH_STATUS是全局变量,这就意味着当第一个游标尚未结束时,当第二个游标的状态=-1时,也会将第一个游标强行结束。
解决的办法是用一个本地的变量,把@@FETCH_STATUS的值赋给此变量后再进行检查。
但是此办法逻辑上并不完备,如果有大量的并发,则可能会造成冲突。
因此如果需要配置后台任务,应该尽可能在时间上分散开来,以避免并发。
下面是相关的参考代码:

---------------------------------------------------------------------------
-- Normally, we use system variable @@FETCH_STATUS to check Cursor loop
DECLARE myCursor CURSOR FOR
SELECT fields FROM Table;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO @myVar;
WHILE @@FETCH_STATUS = 0
BEGIN
  --DO somthing;
END
CLOSE myCursor;
DEALLOCATE myCursor;
 
-- But @@FETCH_STATUS is global variable
-- So if we use another Cursor within the loop, when inner loop is completed, @@FETCH_STATUS = -1, so the outer loop will also be closed.
-- Fixing method is to use local variable instead of @@FETCH_STATUS
DECLARE myCursor CURSOR FOR
SELECT fields FROM Table;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO @myVar;
SET @Outer_loop = @@FETCH_STATUS;
WHILE @Outer_loop = 0
BEGIN
  --inner loop here
  DECLARE myCursor2 CURSOR FOR
  SELECT fields FROM Table2;
  OPEN myCursor2;
  FETCH NEXT FROM myCursor2 INTO @myVar2;
  SET @Inner_loop = @@FETCH_STATUS;
  WHILE @Inner_loop = 0
  BEGIN
    --Inner loop function
FETCH NEXT FROM myCursor2 INTO @myVar2;
    SET @Inner_loop = @@FETCH_STATUS;
  END
  CLOSE myCursor2;
  DEALLOCATE myCursor2;
  FETCH NEXT FROM myCursor INTO @myVar;
  SET @Outer_loop = @@FETCH_STATUS; 
END
CLOSE myCursor;
DEALLOCATE myCursor;
---------------------------------------------------------------------------

2. 关于关联字符集
由于数据库权限方面的限制,我在一个项目中需要对两个数据库中的表进行关联查询,然后碰到了字符集不匹配的报错。
具体的情况是这样的: 数据库DB1采用了GB字符集,数据库DB2采用了LATIN字符集,两个库的表T1和T2通过step_id进行JOIN,而step_id的数据类型是NVARCHAR,因此JOIN失败。
这是因为对于字符串类对象,虽然表示同样的值,当采用不同的字符集时,其存储时的值是不同的。
这个CASE给我的启示是,任何可能用于JOIN或外部引用的对象,要尽可能采用整型数据类型。
事实上,对于数据库来说,整型和日期型数据的检索速度是最快的,当有JOIN、分组查询、外部引用时,要尽可能使用整型数据。

没有评论: