×

Loading...
Ad by
  • 最优利率和cashback可以申请特批,好信用好收入offer更好。请点链接扫码加微信咨询,Scotiabank -- Nick Zhang 6478812600。
Ad by
  • 最优利率和cashback可以申请特批,好信用好收入offer更好。请点链接扫码加微信咨询,Scotiabank -- Nick Zhang 6478812600。

UDF本身不需要读表,纯内存操作和进程间通讯.

本文发表在 rolia.net 枫下论坛steps:

1. write an external UDF and compile:

struct scalar_scratchpad_data
{
int counter;
int cid;
};

void SQL_API_FN ScratchpadScUDF(SQLUDF_INTEGER *inId,
SQLUDF_INTEGER *outCounter,
SQLUDF_SMALLINT *inNullInd,
SQLUDF_SMALLINT *counterNullInd,
SQLUDF_TRAIL_ARGS_ALL)
{
struct scalar_scratchpad_data *pScratData;

pScratData = (struct scalar_scratchpad_data2 *)SQLUDF_SCRAT->data;
switch (SQLUDF_CALLT)
{
case SQLUDF_FIRST_CALL:
pScratData->counter = 1;
pScratData->cid = *inId;
break;
case SQLUDF_NORMAL_CALL:
if (*inId == pScratData->cid)
{
pScratData->counter = pScratData->counter + 1;
}
else
{
pScratData->cid = *inId;
pScratData->counter = 1;
}
break;
case SQLUDF_FINAL_CALL:
break;
}

*outCounter = pScratData->counter;
*counterNullInd = 0;
}

2. define such UDF:
drop FUNCTION ScratchpadScUDF(int);
CREATE FUNCTION ScratchpadScUDF(int) RETURNS INTEGER EXTERNAL NAME 'udfsrv!ScratchpadScUDF' FENCED SCRATCHPAD 100 FINAL CALL VARIANT NO SQL PARAMETER STYLE DB2SQL LANGUAGE C NO EXTERNAL ACTION;

3.
SELECT ScratchpadScUDF(id),id, col1, col2, col3 FROM tbl order by id;
1 ID COL1 COL2 COL3
----------- ----------- ---- ---- ----
1 0 x5 y2 z7
2 0 x5 y4 z3
3 0 x7 y4 z7
4 0 x8 y8 z7
5 0 x2 y0 z5
6 0 x0 y8 z1
7 0 x7 y8 z7
8 0 x1 y1 z1
9 0 x1 y1 z8
10 0 x8 y5 z4
1 1 x8 y6 z4
2 1 x7 y5 z2
3 1 x4 y6 z4
4 1 x9 y0 z2
5 1 x4 y5 z3
6 1 x6 y9 z8
7 1 x1 y0 z1
8 1 x0 y3 z1
9 1 x1 y7 z6
10 1 x6 y0 z9
11 1 x4 y3 z0
12 1 x2 y1 z3
1 2 x3 y0 z1
2 2 x1 y9 z4
3 2 x2 y3 z2
4 2 x4 y1 z4
5 2 x6 y6 z9
6 2 x5 y1 z6
7 2 x1 y5 z9
8 2 x3 y4 z7
9 2 x1 y6 z1
10 2 x6 y8 z7更多精彩文章及讨论,请光临枫下论坛 rolia.net
Report

Replies, comments and Discussions:

  • 工作学习 / 专业技术讨论 / SQL, 还是SQL。又来了。
    一个表tbl。Fields and sample data is:

    id, col1, col2, col3 .....
    1, x1, y2, z1...
    1, x2, y1, z1...
    1, x1, y1, z1..
    1, x2, y2, z2...
    2, x1, y1, z1...
    2, x1, y1, z.1..
    3, x1, y1, z1..
    4, x2, y2, z2...
    4, x1, y1, z1...
    ... ...
    其中col1, col2, col3...里可以是任何内容。现在要增加一个field RowId,是相同id的序列号。要求一个query使得改变后,sample data 为:

    RowId, id, col1, col2, col3 .....
    1, 1, x1, y2, z1...
    2, 1, x2, y1, z1...
    3, 1, x1, y1, z1..
    4, 1, x2, y2, z2...
    1, 2, x1, y1, z1...
    2, 2, x1, y1, z.1..
    1, 3, x1, y1, z1..
    1, 4, x2, y2, z2...
    2, 4, x1, y1, z1...
    ... ...

    有相同id的不同row排序无所谓。也就是说,上面前4行
    1, 1, x1, y2, z1...
    2, 1, x2, y1, z1...
    3, 1, x1, y1, z1..
    4, 1, x2, y2, z2...
    或者
    1, 1, x2, y1, z1...
    2, 1, x1, y1, z1..
    3, 1, x1, y2, z1...
    4, 1, x2, y2, z2...
    都可以。

    题目要求:
    1. 一个query,不能用stored procedure
    2. 使用标准SQL,也就是SQL script 与 DB 无关。
    • It's a good one BDBS, but I don't have a solution yet. Anyone else?
      • 标准SQL干不了这个,要写个程序的。
        • 不需要标准到可以兼容所有早期版本的DB,只要现在流行的一些DB都认就行了。也就是说不要用特殊函数,或者弄个程序放到自定义函数里去。
          • 那些带 OVER() 的函数能用吗? 好多数据库都支持了的。
            • 可以。反正是给大家玩玩的,其实用什么都无所谓。只是为了公平起见。另外也不想太多依赖新功能而忽略SQL本身的一些使用技巧。:)
              • 我的答案不知道是否算标准SQL,但自觉技术含量不高,就不献丑了,呵呵……
                • 这不跟没有答案一样嘛。不说都嫌多。:)
    • 有唯一键吧?COUNT一下ID=当前ID AND KEY<=当前KEY不就行了?
      • 没有唯一键。新生成的RowId和原来的ID共同成为Key。
    • 用partiton by id + row_number(), DB2, Oracle, SQL server 2005 都有。
      • :)
    • Got it.
      1 Assume id + col1 + col2 + col3 is key ,
      2 tested in SQL Server 2005.

      <pre>

      CREATE TABLE t (
      id int,
      col1 varchar(20),
      col2 varchar(20),
      col3 varchar(20)
      )
      GO

      INSERT INTO t
      SELECT 1, 'x1', 'y2', 'z1'
      UNION
      SELECT 1, 'x1', 'y1', 'z1'
      UNION
      SELECT 1, 'x2', 'y2', 'z2'
      UNION
      SELECT 2, 'x1', 'y1', 'z1'
      UNION
      SELECT 3, 'x1', 'y1', 'z1'
      UNION
      SELECT 4, 'x2', 'y2', 'z2'
      UNION
      SELECT 4, 'x1', 'y1', 'z1'

      GO

      SELECT
      (
      SELECT COUNT(*) AS idx
      FROM t t2
      WHERE t2.id = t1.id
      AND t2.col1 <= t1.col1
      AND t2.col2 <= t1.col2
      AND t2.col3 <= t1.col3
      ) AS idx,
      id,
      col1,
      col2,
      col3
      FROM t t1
      GO

      DROP TABLE t
      GO

      </pre>
      • 思路跟我上贴一致,但是:1.楼主说了没有唯一键;2.逻辑有错误
        你预设所有列都是升序,但实际上完全有可能 T2.COL1<T1.COL1 AND T2.COL2>T1.COL2, 这样你COUNT出来的 IDX 有重复值和空洞。
        • 如果没有唯一键,是个问题,会产生你说的空洞。如果有唯一键则不会产生空洞。
          • 不对,关键错误在于t2.col1 <= t1.col1 AND t2.col2 <= t1.col2 AND t2.col3 <= t1.col3,你以为上一行的“每一列”都<=当前列。实际上这是“字典序”,完全有可能 COL1 小, COL2 大。
            • 你再看看题目,搂住说了,顺序没关系
              有相同id的不同row排序无所谓。也就是说,上面前4行
              1, 1, x1, y2, z1...
              2, 1, x2, y1, z1...
              3, 1, x1, y1, z1..
              4, 1, x2, y2, z2...
              或者
              1, 1, x2, y1, z1...
              2, 1, x1, y1, z1..
              3, 1, x1, y2, z1...
              4, 1, x2, y2, z2...
              都可以。
              • 楼主不在乎顺序,但你的COUNT预设了顺序。看看你的WHERE怎么写的?是不是要求IDX=1的“每列”都不大于IDX=2的“每列”?再看看IDX=3和IDX=2,1两行的关系?如果有COL2大于后面的行,你不就算不到了?
                • 明白你的意思了。这种情况下,应该在 Where 后面加一句 ORDER BY id, col1, col2, col3
                  • ORDER BY没有用啊,它是对结果集排序,而你的结果实际上只有一行,就是一个COUNT。其实有办法的,再想想?
                    • 对了! ORDER BY 加在最后。看看这次还有什么问题? 这样修改后的语句是==〉
                      SELECT
                      (
                      SELECT COUNT(*) AS idx
                      FROM t t2
                      WHERE t2.id = t1.id
                      AND t2.col1 <= t1.col1
                      AND t2.col2 <= t1.col2
                      AND t2.col3 <= t1.col3
                      ) AS idx,
                      id,
                      col1,
                      col2,
                      col3
                      FROM t t1
                      ORDER BY i1, col1, col2, col3
                      • 还是不太行啊,试过我给你加的数据了吗?
                        • 刚刚装上SQL Server,试了一下,确实不行,现在改成这样
                          SELECT
                          (
                          SELECT COUNT(*) AS idx
                          FROM t t2
                          WHERE t2.id = t1.id
                          AND
                          (
                          t2.col1 + t2.col2 + t2.col3 <= t1.col1 + t1.col2 + t1.col3
                          )
                          )AS idx,
                          id,
                          col1,
                          col2,
                          col3
                          FROM t t1
                          • 答案必须跟col1,col2,col3等无关。#3333953
                            • 允许自己创建函数么?
                              • 不要用特殊函数,或者弄个程序放到自定义函数里去(#3332558)
                          • 先忽略楼主的限制,我们现在是要拓宽思路,你这个答案已经接近了,但你的假设是所有列都是字符串而且等宽。考虑过 'AB'+'C' 和 'A'+'BC'这种情况了吗?
                            • it looks tricky, but it works for this specific question, alzo not meet LZ' reqirements. >>
                              CREATE TABLE t (
                              id int,
                              col1 varchar(20),
                              col2 varchar(20),
                              col3 varchar(20)
                              )
                              GO

                              INSERT INTO t
                              SELECT 1, 'x1', 'y2', 'z1'
                              UNION
                              SELECT 1, 'x1', 'y1', 'z1'
                              UNION
                              SELECT 1, 'x2', 'y2', 'z2'
                              UNION
                              SELECT 2, 'x1', 'y1', 'z1'
                              UNION
                              SELECT 3, 'x1', 'y1', 'z1'
                              UNION
                              SELECT 4, 'x2', 'y2', 'z2'
                              UNION
                              SELECT 4, 'x1', 'y1', 'z1'
                              UNION
                              SELECT 1, 'x2', 'y1', 'z2'
                              GO

                              SELECT
                              (
                              SELECT COUNT(*) AS idx
                              FROM t t2
                              WHERE t2.id = t1.id AND (
                              t2.col1 < t1.col1 OR (
                              t2.col1 = t1.col1 AND (
                              t2.col2 < t1.col2 OR (
                              t2.col2 = t1.col2 AND t2.col3 <= t1.col3
                              )
                              )
                              )
                              )
                              ) AS idx,
                              id,
                              col1,
                              col2,
                              col3
                              FROM t t1

                              DROP TABLE t
                              GO
                              • 如果这些列中有NULL,结果会受影响,因为NULL不能参与=和><等操作。
                      • 有问题呀。题目col1, col2, col3后面还有...,说明有尚N多个列。所以如果答案肯定得跟col1, col2什么的无关。
        • 如果能保证保证每行的值都是唯一的,使用我上面的方法,最差的结果是把所有的列都加入到Where 子句,此时仍然能得到正确结果。
          • 你倒是写写看?注意,组合列是唯一的并不能保证每列都升序哦。
            • 题目要求区分出同一ID的每一行的编号,并没有要求其他列(col1, col2, col3...)的顺序。
              • 我给你自己的例子加个数据你试试看
                多这么一行:
                UNION
                SELECT 1, 'x2', 'y1', 'z2'

                按你的答案,这行和 1,X1,Y2,Z1 的IDX应该分别是多少?
            • 用COUNT()和GROUP BY COL1, COL2, COL3 就可以了. 但是有DUPLICATE ROW还是不可以.
              • 如果没有重复行,COUNT()出来不全是1了吗?
              • #3333953
                • 看来(不多不少)在考我们! 现在答案只能是在没有DUPLICATE ROW的情况下.
                  没TEST过:
                  select c.rowid, d.*
                  from theTable d,
                  (select count(*) as rowid, a.* from theTable a, theTable b
                  where d.id = a.id and d.id = b.id and
                  concat(a.col1, a.col2, a.col3, ...) >= concat(b.col1, b.col2, b.col3, ...)
                  group by a.col1, a.col2, a.col3 ...) as c
                  order by rowid
                  • 思路正确。然而,一个是需要UPDATE而不单是SELECT,另外见#3333953
                    • Select都有了, UPDATE还用给吗? 结果似乎与跟col1, col2什么的无关, 但需要靠它们当UNIQUE KEY.
                      • 能SELECT不一定能UPDATE哦。OVER()什么的就不行。要用col1col2等做KEY也不错,不过这里有。。。,不仅仅是col1col2col3,还有N多个呢。至少不能HARD CODE。
                        • col1, col2,col3...是COLUMN NAME吧, 这也算HARDCODE? 有点晕. 你的TABLE COULMN不固定? 是啥DATABASE啊?
                          • 题目中col3后面还有...,还有N多column没写出来。那col4~colN怎么办?
                            • N多column是挺难搞的
                              笨点呢就一个字母一个字母地把每个COLUMN NAME锹进去. 聪明点呢就只把那些可以构成UNIQUE KEY的COULMNS敲进去. 如果COLUMN多过N呢,就要再聪明点,用个SELECT把那些COLUMN NAME从SYSCOLUMNS给搞出来并生成个SQL QUERY或部分. 然后CUT&PASTE不用说了吧. 你越来越不象前两天的bdbs(不多不少)喽!我的SELECT没有OVER(),你没问题把它改成UPDATE吧?
                              • 晕!那N多col里面可能是任意类型噢。要是有个什么text或者binary的,你这concat一下得生成多大的东西?还不说得类型转换。此法不妥。
    • --SQL 2005 select rank () over (partition by id order by id, co1, col2, col3) as rank ,id , co1,col2,col3 from ls1 order by id
      • 如果OVER里面的ORDER BY列有重复的,RANK会产生空洞。
      • 什么空洞 ? 唯一会出现的情况就是 相同的rank值。那种情况可以用row_number(). select row_number () over (partition by id order by id, co1, col2, col3) as rank , id , co1,col2,col3 from ls1 order by id
        • 如果重复值后面还有数据就是空洞,例如:1,2,2,4 因为RANK 3没有了。用ROW_NUMBER()可以,OVER 里面ORDER BY随便写啥都行。
          • 光见你点评,怎么不亮亮你的答案?row_number()是一个解。但是我觉得用这个还是太新了点,早一个版本的DB都不支持。我希望看到更tricky一点的解法。比如......用到sys开头的一些表。:)
            • 用 DB2 UDF scratchpad 记录当前状态,返回1或n+1.
              • 不要用特殊函数,或者弄个程序放到自定义函数里去(#3332558)
                • 有点钻牛角尖啦,究竟是写一个优化的SQL还是一个巨慢的'传统'的SQL? 那种能更让人满意?自定义函数并不难,也容易移植. 如果只为追求SQL的技巧,这就本末倒置.
                  • 巨快当然比巨慢好。只是我觉得一旦用到程序(自定义函数),必定会造成对ROW的操作(cursor)而不是dataset,必定会巨慢。也许我错了。把你的方案拿来看看吧。
                    • 自定义函数完全可以是对内存变量的计算操作,不用读表,只是有进出堆栈等开销。
                      • 这句有歧义。任何的一个cursor操作都应该在内存中的计算操作,无论是显式的或是隐式的。但是自定义的函数应该都会对row有read的操作,而不是只是进出堆栈等开销。比如自定义函数中的sum操作性能一定要比sum + group by 差很多很多。
                    • UDF本身不需要读表,纯内存操作和进程间通讯.
                      本文发表在 rolia.net 枫下论坛steps:

                      1. write an external UDF and compile:

                      struct scalar_scratchpad_data
                      {
                      int counter;
                      int cid;
                      };

                      void SQL_API_FN ScratchpadScUDF(SQLUDF_INTEGER *inId,
                      SQLUDF_INTEGER *outCounter,
                      SQLUDF_SMALLINT *inNullInd,
                      SQLUDF_SMALLINT *counterNullInd,
                      SQLUDF_TRAIL_ARGS_ALL)
                      {
                      struct scalar_scratchpad_data *pScratData;

                      pScratData = (struct scalar_scratchpad_data2 *)SQLUDF_SCRAT->data;
                      switch (SQLUDF_CALLT)
                      {
                      case SQLUDF_FIRST_CALL:
                      pScratData->counter = 1;
                      pScratData->cid = *inId;
                      break;
                      case SQLUDF_NORMAL_CALL:
                      if (*inId == pScratData->cid)
                      {
                      pScratData->counter = pScratData->counter + 1;
                      }
                      else
                      {
                      pScratData->cid = *inId;
                      pScratData->counter = 1;
                      }
                      break;
                      case SQLUDF_FINAL_CALL:
                      break;
                      }

                      *outCounter = pScratData->counter;
                      *counterNullInd = 0;
                      }

                      2. define such UDF:
                      drop FUNCTION ScratchpadScUDF(int);
                      CREATE FUNCTION ScratchpadScUDF(int) RETURNS INTEGER EXTERNAL NAME 'udfsrv!ScratchpadScUDF' FENCED SCRATCHPAD 100 FINAL CALL VARIANT NO SQL PARAMETER STYLE DB2SQL LANGUAGE C NO EXTERNAL ACTION;

                      3.
                      SELECT ScratchpadScUDF(id),id, col1, col2, col3 FROM tbl order by id;
                      1 ID COL1 COL2 COL3
                      ----------- ----------- ---- ---- ----
                      1 0 x5 y2 z7
                      2 0 x5 y4 z3
                      3 0 x7 y4 z7
                      4 0 x8 y8 z7
                      5 0 x2 y0 z5
                      6 0 x0 y8 z1
                      7 0 x7 y8 z7
                      8 0 x1 y1 z1
                      9 0 x1 y1 z8
                      10 0 x8 y5 z4
                      1 1 x8 y6 z4
                      2 1 x7 y5 z2
                      3 1 x4 y6 z4
                      4 1 x9 y0 z2
                      5 1 x4 y5 z3
                      6 1 x6 y9 z8
                      7 1 x1 y0 z1
                      8 1 x0 y3 z1
                      9 1 x1 y7 z6
                      10 1 x6 y0 z9
                      11 1 x4 y3 z0
                      12 1 x2 y1 z3
                      1 2 x3 y0 z1
                      2 2 x1 y9 z4
                      3 2 x2 y3 z2
                      4 2 x4 y1 z4
                      5 2 x6 y6 z9
                      6 2 x5 y1 z6
                      7 2 x1 y5 z9
                      8 2 x3 y4 z7
                      9 2 x1 y6 z1
                      10 2 x6 y8 z7更多精彩文章及讨论,请光临枫下论坛 rolia.net
                      • UDF不需要读表这个问题,小弟想跟各位老大讨教一下。比如有一个table, ID int , QTY number(9,2)
                        定义UDF udf_test (id int ) select @Total = sum (QTY) from table where id =@id retrun Total

                        如果 "UDF本身不需要读表,纯内存操作和进程间通讯"的话,那么
                        select id, udf_test (@id) from table
                        group by id



                        select id, sum(QTY)
                        group by id

                        的效率应该一样。为什么用UDF的query要比直接group by 的慢很多呢?
                        • 因为每次调用udf_test()都需要读表,如果有n个不同的id, 就要n+1次读表。直接用SQL只需读表一次。
                          • 对啊,那这个'UDF"是需要读表的。所以看到你们说" UDF本身不需要读表",我觉得这句话不对。
                            • 我想上面newkid的意思是说可以用一个不读表的UDF来辅助实现复杂功能。UDF也就是一个小程序,这个小程序读不读表就看写程序的人怎么写了。这也是题目要求不能用SP,用UDF的原因。
                        • 没人说一定读表或一定不读表啊?这完全取决于你在函数中作了什么事。我的原则是:不在WHERE中调用自定义函数;尽量避免对表的存取。自定义函数的好处是使得SQL更为整洁易于维护。
                          • WHERE中调用函数的话只放右边,COLUMN不参与计算
            • 如果能用ORACLE的 ROWNUM, ROWID 等伪列,答案是很FLEXIBLE的。OVER()函数我用得多了,感觉没啥技术含量,写出来怕破坏别人兴致。我现在想看有没有人用传统办法写出来,我是放弃了。不过你提到的什么SYS表那可是违背了自己的DB通用原则啊。
              • SYS表怎么不通用了?顶多不同DB的SYS表名称不同,结构内容应该是大同小异的。
          • 想到一个问题,over () 什么的不能用在update的。原题是要update呀。
            • 你说的是“增加一列”,CREATE NEW_TABLE AS SELECT ... 不就行了?说出你的答案吧,我这等着景仰呢!
              • 我的答案来了,对MS SQL 2000,2005适用。如果要移植到其它DB,需作改动。
                UDPATE a
                SET RowId = (SELECT COUNT(*) FROM tbl WHERE id =a.id and CHECKSUM(*) <= a.chksum)
                FROM (SELECT id, CHECKSUM(*) as chksum FROM tbl) a

                需要改动的原因是CHECKSUM这个函数在其它DB上名称和语法会有点不同吧。这个答案的唯一缺陷是,如果有内容完全相同的两行,结果就会出错。:(不过实际应用应该很少会出现这样的情况。

                说实话对这个答案也还不是最满意,不过希望扔一砖头能引出一些高手的玉来。
                • 你这答案就是我的#3332542,只不过人为用CHECKSUM造出一个KEY.首先,你也承认重复的两行CHECKSUM会重复;其次,哪怕是不同的两行,CHECKSUM也可能重复。按我的理解这是一个HASH算法,因此有碰撞(即使机会很小)。如果用ORACLE,伪列ROWID是个物理地址,保证不重复!
                  • 难就难在这里,需要人为的弄个KEY出来。不同的两行,CHECKSUM(*)不可能重复。上面的答案错了,漏了一点,修正如下。另外需要更正,根据实际运行,这个query在MS SQL 2000下面不行。我说了,自己对这个答案不满意。希望有更好的。
                    UDPATE a
                    SET RowId = (SELECT COUNT(*) FROM tbl WHERE id =a.id and CHECKSUM(*) <= a.chksum)
                    FROM (SELECT id, RowId, CHECKSUM(*) as chksum FROM tbl) a
                    • 谁说CHECKSUM不可能重复?给你看微软的链接:
                      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_ca-co_9p2h.asp

                      .........
                      If one of the values in the expression list changes, the checksum of the list also usually changes. However, there is a small chance that the checksum will not change.
                      .........
                      • 再仔细看看?就是仅有的那么丁点的可能性,跟这里的用法也没有关系吧。

                        .........

                        If one of the values in the expression list
                        changes, the checksum of the list also usually changes. However, there is a small chance that the checksum will not change.

                        .........

                        • I服了U,你竟然认为用*就不会有重复了?*不过是一种简便的写法,编译器自然会帮你转换成COL1,COL2,...这样的expression list!去复习一下HASH算法的定义吧。重复机会是很小,那又如何?再小的漏洞也是漏洞。为了构造唯一的KEY,你就得有无懈可击的算法。
                          • 不是用不用*的问题。文档是说某个值改变后相应的HASH可能会没有跟着改变,这是一个动态过程中的问题,而不是静态的。对于本题,是个一次过的UPDATE,是个相对静态的问题。所以我说跟这里的用法没关系。
                            • 什么动态静态啊!文档说:输入的改变不一定引起结果的改变;也就是说,不同的输入可能算出相同的CHECKSUM。按你的说法,你这段SQL调用的CHECKSUM叫动态还是静态?
                              • 咱们理解不同。找个实例试试就行了。本来嘛,我也说了不满意这个答案,你倒是出个更好的吧,别光说不练呀!
                                • 找实例试试,谈何容易,要不然当年王小云破解MD5(即有限时间内找到碰撞)就不会那么轰动了。另外,你这CHECKSUM(*)可是很耗费CPU的哟。我没有什么好答案,就等看别人的呢。
                                  • CHECKSUM是通常用来做INDEX的. 当CHECKSUM INDEX的实际上的COLUMN如果有小的改变, 可能INDEX(CHECKSUM)值不会变. 我想这就是LZ的静态吧. 但CHECKSUM()用在QUERY里和用在INDEX上也许会有不同的结果吧. 开始还以为LZ有完美的答案, 看来是没希望了
                                    • 我这可也是来找答案的呀。等俺琢磨出更好的答案一定过来跟大伙儿交流。
                                  • 我来举个实例,checksum没用,checksum不能保证唯一性。;)
                                    本文发表在 rolia.net 枫下论坛create table ttt (i1 int, i2 varchar(200));
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789B');
                                    insert into ttt values (1,'123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789A123456789A23456789B');
                                    go

                                    select i1, checksum(*) as chksum from ttt
                                    go

                                    i1 chksum
                                    ----------- -----------
                                    1 -1403808475
                                    1 -1403808475
                                    1 -1403808475
                                    1 -1403808475
                                    1 -1403808475
                                    1 -1403808466
                                    1 -1403808466更多精彩文章及讨论,请光临枫下论坛 rolia.net
                                    • 小伙子,知道我们在讨论什么吗?知道我们在说什么东西重复不重复么?看仔细些再答题。
                                      • 你没看出来?checksum只有10位有效位, 200位的字符串很容易就找到相同的HASH值,实际上,5位 字符串就够了 ;)
                                    • 诈胡了一把,重举一例. checksum真是一点也靠不住.
                                      create table tx (i1 char(10) not null)

                                      insert into tx values ('abcdPWJ0')
                                      insert into tx values ('abcdovg2')
                                      insert into tx values ('abcdYQVY')
                                      insert into tx values ('abcdvqry')
                                      insert into tx values ('abcdG407')
                                      insert into tx values ('abcdf427')

                                      select i1, checksum(*) as chksum from tx
                                      go

                                      i1 chksum
                                      ---------- -----------
                                      abcdPWJ0 -1124508945
                                      abcdovg2 -1124508945
                                      abcdYQVY 1895630318
                                      abcdvqry 1895630318
                                      abcdG407 -806636310
                                      abcdf427 -806636310
                                      • 啊?真是出乎意料,CHECKSUM一般可以用于检验数据是否被篡改过的。ORACLE有个ORA_HASH比这可靠多了。
                                        • 是有点离谱,4位字符串就能轻松找出一大堆重复.微软的checksum算法还是太naive了.
                                          • #3342478
                                      • 又诈胡?运行你的code,这是我的运行结果。
                                        abcdPWJ0 1721269756
                                        abcdovg2 1721264846
                                        abcdYQVY 1721496734
                                        abcdvqry 1721476958
                                        abcdG407 1721286851
                                        abcdf427 1721282787


                                        增加点长度:

                                        create table tx (i1 char(30) not null)

                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzPWJ0')
                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzovg2')
                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzYQVY')
                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzvqry')
                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzG407')
                                        insert into tx values ('abcdefghijklmnopqrstuvwxyzf427')

                                        select i1, checksum(*) as chksum from tx

                                        abcdefghijklmnopqrstuvwxyzPWJ0 1864589045
                                        abcdefghijklmnopqrstuvwxyzovg2 1864583623
                                        abcdefghijklmnopqrstuvwxyzYQVY 1864423319
                                        abcdefghijklmnopqrstuvwxyzvqry 1864402007
                                        abcdefghijklmnopqrstuvwxyzG407 1864623050
                                        abcdefghijklmnopqrstuvwxyzf427 1864602602
                                        • 你我操作系统,软件版本,数据库collation,以及其他环境不一定都相同, 不能重复也很正常. 你只要遍历4位的ascII码, 就能找出一大把重复. 原理都告诉你了,找不找出来,就是你的能力问题了.
                        • 你看不出bug是能力问题,看出bug不管是态度问题,这种code能进产品就是公司的问题. ;)
                • M$ does not guaranty that CHECKSUM returns different value for different rows even they have different values, regardless your 动态静态.
                • 你现在是用SQLSERVER吧, 要不先搞移植的吧, 然后再想现在的.
                  用CREATE SEQUENCE吧, 就TNND M$没有.
                  • 移植还不如移到oracle,#3334352 :)