【问题标题】:Does SQL Server CheckSum calculate a CRC? If not how can I get MS SQL to calculate a CRC on an arbitrary varchar column?SQL Server CheckSum 是否计算 CRC?如果不是,我怎样才能让 MS SQL 在任意 varchar 列上计算 CRC?
【发布时间】:2013-06-30 11:24:07
【问题描述】:

SQL Server CheckSum 是否计算 CRC?如果不是,我怎样才能让 SQL Server 在任意 varchar 列上计算 CRC?

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我对模型的粗鲁表示歉意,但这似乎可以进行正确的 CRC32 计算。 我不是 TSQL 专家,我相信真正的 SQL Server 专业人士可以大大改善这一点......

    @input 是计算 CRC32 的变量。 将其打包为 sproc 或 udf 应该很简单,并且可以将查找表分解为永久表(甚至可以即时计算)。

    无论如何,它似乎工作。我有兴趣看到任何改进,因为学习新技巧总是好的:)

    编辑:我已经对照http://crc32-checksum.waraxe.us/ 检查了我的结果,目前看来还不错。

    安德鲁

    DECLARE @input VARCHAR(50)
    SET @input = 'test'
    
    SET NOCOUNT ON
    DECLARE @tblLookup TABLE (ID INT IDENTITY(0,1) NOT NULL, Value BIGINT)
    INSERT INTO @tblLookup VALUES (0)
    INSERT INTO @tblLookup VALUES (1996959894)
    INSERT INTO @tblLookup VALUES (3993919788)
    INSERT INTO @tblLookup VALUES (2567524794)
    INSERT INTO @tblLookup VALUES (124634137)
    INSERT INTO @tblLookup VALUES (1886057615)
    INSERT INTO @tblLookup VALUES (3915621685)
    INSERT INTO @tblLookup VALUES (2657392035)
    INSERT INTO @tblLookup VALUES (249268274)
    INSERT INTO @tblLookup VALUES (2044508324)
    INSERT INTO @tblLookup VALUES (3772115230)
    INSERT INTO @tblLookup VALUES (2547177864)
    INSERT INTO @tblLookup VALUES (162941995)
    INSERT INTO @tblLookup VALUES (2125561021)
    INSERT INTO @tblLookup VALUES (3887607047)
    INSERT INTO @tblLookup VALUES (2428444049)
    INSERT INTO @tblLookup VALUES (498536548)
    INSERT INTO @tblLookup VALUES (1789927666)
    INSERT INTO @tblLookup VALUES (4089016648)
    INSERT INTO @tblLookup VALUES (2227061214)
    INSERT INTO @tblLookup VALUES (450548861)
    INSERT INTO @tblLookup VALUES (1843258603)
    INSERT INTO @tblLookup VALUES (4107580753)
    INSERT INTO @tblLookup VALUES (2211677639)
    INSERT INTO @tblLookup VALUES (325883990)
    INSERT INTO @tblLookup VALUES (1684777152)
    INSERT INTO @tblLookup VALUES (4251122042)
    INSERT INTO @tblLookup VALUES (2321926636)
    INSERT INTO @tblLookup VALUES (335633487)
    INSERT INTO @tblLookup VALUES (1661365465)
    INSERT INTO @tblLookup VALUES (4195302755)
    INSERT INTO @tblLookup VALUES (2366115317)
    INSERT INTO @tblLookup VALUES (997073096)
    INSERT INTO @tblLookup VALUES (1281953886)
    INSERT INTO @tblLookup VALUES (3579855332)
    INSERT INTO @tblLookup VALUES (2724688242)
    INSERT INTO @tblLookup VALUES (1006888145)
    INSERT INTO @tblLookup VALUES (1258607687)
    INSERT INTO @tblLookup VALUES (3524101629)
    INSERT INTO @tblLookup VALUES (2768942443)
    INSERT INTO @tblLookup VALUES (901097722)
    INSERT INTO @tblLookup VALUES (1119000684)
    INSERT INTO @tblLookup VALUES (3686517206)
    INSERT INTO @tblLookup VALUES (2898065728)
    INSERT INTO @tblLookup VALUES (853044451)
    INSERT INTO @tblLookup VALUES (1172266101)
    INSERT INTO @tblLookup VALUES (3705015759)
    INSERT INTO @tblLookup VALUES (2882616665)
    INSERT INTO @tblLookup VALUES (651767980)
    INSERT INTO @tblLookup VALUES (1373503546)
    INSERT INTO @tblLookup VALUES (3369554304)
    INSERT INTO @tblLookup VALUES (3218104598)
    INSERT INTO @tblLookup VALUES (565507253)
    INSERT INTO @tblLookup VALUES (1454621731)
    INSERT INTO @tblLookup VALUES (3485111705)
    INSERT INTO @tblLookup VALUES (3099436303)
    INSERT INTO @tblLookup VALUES (671266974)
    INSERT INTO @tblLookup VALUES (1594198024)
    INSERT INTO @tblLookup VALUES (3322730930)
    INSERT INTO @tblLookup VALUES (2970347812)
    INSERT INTO @tblLookup VALUES (795835527)
    INSERT INTO @tblLookup VALUES (1483230225)
    INSERT INTO @tblLookup VALUES (3244367275)
    INSERT INTO @tblLookup VALUES (3060149565)
    INSERT INTO @tblLookup VALUES (1994146192)
    INSERT INTO @tblLookup VALUES (31158534)
    INSERT INTO @tblLookup VALUES (2563907772)
    INSERT INTO @tblLookup VALUES (4023717930)
    INSERT INTO @tblLookup VALUES (1907459465)
    INSERT INTO @tblLookup VALUES (112637215)
    INSERT INTO @tblLookup VALUES (2680153253)
    INSERT INTO @tblLookup VALUES (3904427059)
    INSERT INTO @tblLookup VALUES (2013776290)
    INSERT INTO @tblLookup VALUES (251722036)
    INSERT INTO @tblLookup VALUES (2517215374)
    INSERT INTO @tblLookup VALUES (3775830040)
    INSERT INTO @tblLookup VALUES (2137656763)
    INSERT INTO @tblLookup VALUES (141376813)
    INSERT INTO @tblLookup VALUES (2439277719)
    INSERT INTO @tblLookup VALUES (3865271297)
    INSERT INTO @tblLookup VALUES (1802195444)
    INSERT INTO @tblLookup VALUES (476864866)
    INSERT INTO @tblLookup VALUES (2238001368)
    INSERT INTO @tblLookup VALUES (4066508878)
    INSERT INTO @tblLookup VALUES (1812370925)
    INSERT INTO @tblLookup VALUES (453092731)
    INSERT INTO @tblLookup VALUES (2181625025)
    INSERT INTO @tblLookup VALUES (4111451223)
    INSERT INTO @tblLookup VALUES (1706088902)
    INSERT INTO @tblLookup VALUES (314042704)
    INSERT INTO @tblLookup VALUES (2344532202)
    INSERT INTO @tblLookup VALUES (4240017532)
    INSERT INTO @tblLookup VALUES (1658658271)
    INSERT INTO @tblLookup VALUES (366619977)
    INSERT INTO @tblLookup VALUES (2362670323)
    INSERT INTO @tblLookup VALUES (4224994405)
    INSERT INTO @tblLookup VALUES (1303535960)
    INSERT INTO @tblLookup VALUES (984961486)
    INSERT INTO @tblLookup VALUES (2747007092)
    INSERT INTO @tblLookup VALUES (3569037538)
    INSERT INTO @tblLookup VALUES (1256170817)
    INSERT INTO @tblLookup VALUES (1037604311)
    INSERT INTO @tblLookup VALUES (2765210733)
    INSERT INTO @tblLookup VALUES (3554079995)
    INSERT INTO @tblLookup VALUES (1131014506)
    INSERT INTO @tblLookup VALUES (879679996)
    INSERT INTO @tblLookup VALUES (2909243462)
    INSERT INTO @tblLookup VALUES (3663771856)
    INSERT INTO @tblLookup VALUES (1141124467)
    INSERT INTO @tblLookup VALUES (855842277)
    INSERT INTO @tblLookup VALUES (2852801631)
    INSERT INTO @tblLookup VALUES (3708648649)
    INSERT INTO @tblLookup VALUES (1342533948)
    INSERT INTO @tblLookup VALUES (654459306)
    INSERT INTO @tblLookup VALUES (3188396048)
    INSERT INTO @tblLookup VALUES (3373015174)
    INSERT INTO @tblLookup VALUES (1466479909)
    INSERT INTO @tblLookup VALUES (544179635)
    INSERT INTO @tblLookup VALUES (3110523913)
    INSERT INTO @tblLookup VALUES (3462522015)
    INSERT INTO @tblLookup VALUES (1591671054)
    INSERT INTO @tblLookup VALUES (702138776)
    INSERT INTO @tblLookup VALUES (2966460450)
    INSERT INTO @tblLookup VALUES (3352799412)
    INSERT INTO @tblLookup VALUES (1504918807)
    INSERT INTO @tblLookup VALUES (783551873)
    INSERT INTO @tblLookup VALUES (3082640443)
    INSERT INTO @tblLookup VALUES (3233442989)
    INSERT INTO @tblLookup VALUES (3988292384)
    INSERT INTO @tblLookup VALUES (2596254646)
    INSERT INTO @tblLookup VALUES (62317068)
    INSERT INTO @tblLookup VALUES (1957810842)
    INSERT INTO @tblLookup VALUES (3939845945)
    INSERT INTO @tblLookup VALUES (2647816111)
    INSERT INTO @tblLookup VALUES (81470997)
    INSERT INTO @tblLookup VALUES (1943803523)
    INSERT INTO @tblLookup VALUES (3814918930)
    INSERT INTO @tblLookup VALUES (2489596804)
    INSERT INTO @tblLookup VALUES (225274430)
    INSERT INTO @tblLookup VALUES (2053790376)
    INSERT INTO @tblLookup VALUES (3826175755)
    INSERT INTO @tblLookup VALUES (2466906013)
    INSERT INTO @tblLookup VALUES (167816743)
    INSERT INTO @tblLookup VALUES (2097651377)
    INSERT INTO @tblLookup VALUES (4027552580)
    INSERT INTO @tblLookup VALUES (2265490386)
    INSERT INTO @tblLookup VALUES (503444072)
    INSERT INTO @tblLookup VALUES (1762050814)
    INSERT INTO @tblLookup VALUES (4150417245)
    INSERT INTO @tblLookup VALUES (2154129355)
    INSERT INTO @tblLookup VALUES (426522225)
    INSERT INTO @tblLookup VALUES (1852507879)
    INSERT INTO @tblLookup VALUES (4275313526)
    INSERT INTO @tblLookup VALUES (2312317920)
    INSERT INTO @tblLookup VALUES (282753626)
    INSERT INTO @tblLookup VALUES (1742555852)
    INSERT INTO @tblLookup VALUES (4189708143)
    INSERT INTO @tblLookup VALUES (2394877945)
    INSERT INTO @tblLookup VALUES (397917763)
    INSERT INTO @tblLookup VALUES (1622183637)
    INSERT INTO @tblLookup VALUES (3604390888)
    INSERT INTO @tblLookup VALUES (2714866558)
    INSERT INTO @tblLookup VALUES (953729732)
    INSERT INTO @tblLookup VALUES (1340076626)
    INSERT INTO @tblLookup VALUES (3518719985)
    INSERT INTO @tblLookup VALUES (2797360999)
    INSERT INTO @tblLookup VALUES (1068828381)
    INSERT INTO @tblLookup VALUES (1219638859)
    INSERT INTO @tblLookup VALUES (3624741850)
    INSERT INTO @tblLookup VALUES (2936675148)
    INSERT INTO @tblLookup VALUES (906185462)
    INSERT INTO @tblLookup VALUES (1090812512)
    INSERT INTO @tblLookup VALUES (3747672003)
    INSERT INTO @tblLookup VALUES (2825379669)
    INSERT INTO @tblLookup VALUES (829329135)
    INSERT INTO @tblLookup VALUES (1181335161)
    INSERT INTO @tblLookup VALUES (3412177804)
    INSERT INTO @tblLookup VALUES (3160834842)
    INSERT INTO @tblLookup VALUES (628085408)
    INSERT INTO @tblLookup VALUES (1382605366)
    INSERT INTO @tblLookup VALUES (3423369109)
    INSERT INTO @tblLookup VALUES (3138078467)
    INSERT INTO @tblLookup VALUES (570562233)
    INSERT INTO @tblLookup VALUES (1426400815)
    INSERT INTO @tblLookup VALUES (3317316542)
    INSERT INTO @tblLookup VALUES (2998733608)
    INSERT INTO @tblLookup VALUES (733239954)
    INSERT INTO @tblLookup VALUES (1555261956)
    INSERT INTO @tblLookup VALUES (3268935591)
    INSERT INTO @tblLookup VALUES (3050360625)
    INSERT INTO @tblLookup VALUES (752459403)
    INSERT INTO @tblLookup VALUES (1541320221)
    INSERT INTO @tblLookup VALUES (2607071920)
    INSERT INTO @tblLookup VALUES (3965973030)
    INSERT INTO @tblLookup VALUES (1969922972)
    INSERT INTO @tblLookup VALUES (40735498)
    INSERT INTO @tblLookup VALUES (2617837225)
    INSERT INTO @tblLookup VALUES (3943577151)
    INSERT INTO @tblLookup VALUES (1913087877)
    INSERT INTO @tblLookup VALUES (83908371)
    INSERT INTO @tblLookup VALUES (2512341634)
    INSERT INTO @tblLookup VALUES (3803740692)
    INSERT INTO @tblLookup VALUES (2075208622)
    INSERT INTO @tblLookup VALUES (213261112)
    INSERT INTO @tblLookup VALUES (2463272603)
    INSERT INTO @tblLookup VALUES (3855990285)
    INSERT INTO @tblLookup VALUES (2094854071)
    INSERT INTO @tblLookup VALUES (198958881)
    INSERT INTO @tblLookup VALUES (2262029012)
    INSERT INTO @tblLookup VALUES (4057260610)
    INSERT INTO @tblLookup VALUES (1759359992)
    INSERT INTO @tblLookup VALUES (534414190)
    INSERT INTO @tblLookup VALUES (2176718541)
    INSERT INTO @tblLookup VALUES (4139329115)
    INSERT INTO @tblLookup VALUES (1873836001)
    INSERT INTO @tblLookup VALUES (414664567)
    INSERT INTO @tblLookup VALUES (2282248934)
    INSERT INTO @tblLookup VALUES (4279200368)
    INSERT INTO @tblLookup VALUES (1711684554)
    INSERT INTO @tblLookup VALUES (285281116)
    INSERT INTO @tblLookup VALUES (2405801727)
    INSERT INTO @tblLookup VALUES (4167216745)
    INSERT INTO @tblLookup VALUES (1634467795)
    INSERT INTO @tblLookup VALUES (376229701)
    INSERT INTO @tblLookup VALUES (2685067896)
    INSERT INTO @tblLookup VALUES (3608007406)
    INSERT INTO @tblLookup VALUES (1308918612)
    INSERT INTO @tblLookup VALUES (956543938)
    INSERT INTO @tblLookup VALUES (2808555105)
    INSERT INTO @tblLookup VALUES (3495958263)
    INSERT INTO @tblLookup VALUES (1231636301)
    INSERT INTO @tblLookup VALUES (1047427035)
    INSERT INTO @tblLookup VALUES (2932959818)
    INSERT INTO @tblLookup VALUES (3654703836)
    INSERT INTO @tblLookup VALUES (1088359270)
    INSERT INTO @tblLookup VALUES (936918000)
    INSERT INTO @tblLookup VALUES (2847714899)
    INSERT INTO @tblLookup VALUES (3736837829)
    INSERT INTO @tblLookup VALUES (1202900863)
    INSERT INTO @tblLookup VALUES (817233897)
    INSERT INTO @tblLookup VALUES (3183342108)
    INSERT INTO @tblLookup VALUES (3401237130)
    INSERT INTO @tblLookup VALUES (1404277552)
    INSERT INTO @tblLookup VALUES (615818150)
    INSERT INTO @tblLookup VALUES (3134207493)
    INSERT INTO @tblLookup VALUES (3453421203)
    INSERT INTO @tblLookup VALUES (1423857449)
    INSERT INTO @tblLookup VALUES (601450431)
    INSERT INTO @tblLookup VALUES (3009837614)
    INSERT INTO @tblLookup VALUES (3294710456)
    INSERT INTO @tblLookup VALUES (1567103746)
    INSERT INTO @tblLookup VALUES (711928724)
    INSERT INTO @tblLookup VALUES (3020668471)
    INSERT INTO @tblLookup VALUES (3272380065)
    INSERT INTO @tblLookup VALUES (1510334235)
    INSERT INTO @tblLookup VALUES (755167117)
    
    DECLARE @crc BIGINT, @len INT, @i INT, @index INT
    DECLARE @tblval BIGINT
    SET @crc = 0xFFFFFFFF
    SET @len = LEN(@input)
    SET @i = 1
    
    WHILE @i <= @len
    BEGIN
        SET @index = ((@crc & 0xff) ^ ASCII(SUBSTRING(@input, @i, 1)))  
        SET @tblval = (SELECT Value FROM @tblLookup WHERE ID = @Index)
        SET @crc = (@crc / 256) ^ @tblval   
        SET @i = @i + 1 
    END
    SET @crc = ~@crc
    
    SELECT @crc as CRC32, CONVERT(VARBINARY(4), @crc) as CRC32Hex
    

    【讨论】:

    • 我忘记输入编辑注释,但我在 TSQL 脚本的最后一行添加了“AS CRC32”,使其命名为选定的列。
    • 我会明确地将索引值放入您的查找表中,而不是依赖 IDENTITY。由于表是本地的,因此您的方法应该 100% 的时间有效,但不能保证 IDENTITY 创建 seq 值。不过大多只是我的一个习惯。如果你知道值,不妨把它放进去
    • 嗯...不知道。 TSQL 文档似乎另有说明:“IDENTITY [(种子,增量)] 种子:是用于加载到表中的第一行的值增量:是添加到前一个标识值的增量值已加载的行。"
    • @Andrew:如果插入回滚,插入的值将包含一个间隙。还有其他原因可能会导致出现差距,但没有一个真正适用于您的情况。就像我说的,在你的代码中你应该是安全的。当我出于习惯了解它们(包括递增#s)时,我会陈述它们。
    • @Andrew 请参阅 my answer 以获取缩短版本。
    【解决方案2】:

    我将 Andrew Rollings 的剧本缩短到 11 行,因此他确实得到了赞誉。这将在 SQL 2008 或更高版本中运行。如果在 DECLARE 之后设置变量值,它将在 SQL 2005 中运行。在 2005 年及以后,字符限制为 2048,在 SQL 2000 中,它类似于 512(我不记得在 SQL 中有多少 P 类型的 spt_value 2000)。但如有必要,可以对其进行修改。

    DECLARE @input VARCHAR(50)
    SET @input = 'test'
    
    SET NOCOUNT ON
    DECLARE
        @crc bigint = 0xFFFFFFFF,
        @Lookup varbinary(2048) = 0x0000000077073096EE0E612C990951BA076DC419706AF48FE963A5359E6495A30EDB883279DCB8A4E0D5E91E97D2D98809B64C2B7EB17CBDE7B82D0790BF1D911DB710646AB020F2F3B9714884BE41DE1ADAD47D6DDDE4EBF4D4B55183D385C7136C9856646BA8C0FD62F97A8A65C9EC14015C4F63066CD9FA0F3D638D080DF53B6E20C84C69105ED56041E4A26771723C03E4D14B04D447D20D85FDA50AB56B35B5A8FA42B2986CDBBBC9D6ACBCF94032D86CE345DF5C75DCD60DCFABD13D5926D930AC51DE003AC8D75180BFD0611621B4F4B556B3C423CFBA9599B8BDA50F2802B89E5F058808C60CD9B2B10BE9242F6F7C8758684C11C1611DABB6662D3D76DC419001DB710698D220BCEFD5102A71B1858906B6B51F9FBFE4A5E8B8D4337807C9A20F00F9349609A88EE10E98187F6A0DBB086D3D2D91646C97E6635C016B6B51F41C6C6162856530D8F262004E6C0695ED1B01A57B8208F4C1F50FC45765B0D9C612B7E9508BBEB8EAFCB9887C62DD1DDF15DA2D498CD37CF3FBD44C654DB261583AB551CEA3BC0074D4BB30E24ADFA5413DD895D7A4D1C46DD3D6F4FB4369E96A346ED9FCAD678846DA60B8D044042D7333031DE5AA0A4C5FDD0D7CC95005713C270241AABE0B1010C90C20865768B525206F85B3B966D409CE61E49F5EDEF90E29D9C998B0D09822C7D7A8B459B33D172EB40D81B7BD5C3BC0BA6CADEDB883209ABFB3B603B6E20C74B1D29AEAD547399DD277AF04DB261573DC1683E3630B1294643B840D6D6A3E7A6A5AA8E40ECF0B9309FF9D0A00AE277D079EB1F00F93448708A3D21E01F2686906C2FEF762575D806567CB196C36716E6B06E7FED41B7689D32BE010DA7A5A67DD4ACCF9B9DF6F8EBEEFF917B7BE4360B08ED5D6D6A3E8A1D1937E38D8C2C44FDFF252D1BB67F1A6BC57673FB506DD48B2364BD80D2BDAAF0A1B4C36034AF641047A60DF60EFC3A867DF55316E8EEF4669BE79CB61B38CBC66831A256FD2A05268E236CC0C7795BB0B4703220216B95505262FC5BA3BBEB2BD0B282BB45A925CB36A04C2D7FFA7B5D0CF312CD99E8B5BDEAE1D9B64C2B0EC63F226756AA39C026D930A9C0906A9EB0E363F720767850500571395BF4A82E2B87A147BB12BAE0CB61B3892D28E9BE5D5BE0D7CDCEFB70BDBDF2186D3D2D4F1D4E24268DDB3F81FDA836E81BE16CDF6B9265B6FB077E118B7477788085AE6FF0F6A7066063BCA11010B5C8F659EFFF862AE69616BFFD3166CCF45A00AE278D70DD2EE4E0483543903B3C2A7672661D06016F74969474D3E6E77DBAED16A4AD9D65ADC40DF0B6637D83BF0A9BCAE53DEBB9EC547B2CF7F30B5FFE9BDBDF21CCABAC28A53B3933024B4A3A6BAD03605CDD7069354DE572923D967BFB3667A2EC4614AB85D681B022A6F2B94B40BBE37C30C8EA15A05DF1B2D02EF8D;
    
    SELECT @crc = (@crc / 256) ^ Substring(@Lookup, ((@crc & 0xFF) ^ Ascii(Substring(@input, V.Number, 1))) * 4 + 1, 4)
    FROM master.dbo.spt_values V
    WHERE V.type = 'P' AND V.number BETWEEN 1 AND Len(@input)
    
    SET @crc = ~@crc;
    SELECT @crc CRC32, Convert(VARBINARY(4), @crc) CRC32Hex;
    

    【讨论】:

    • 嗯,一些进一步的分析表明我应该检查 CRC 是否真的以正确的顺序计算。如果来自master.dbo.spt_values 的行顺序错误,则CRC 错误。
    【解决方案3】:

    对于任何需要这种函数形式的人,我从 Andrew Rollings 和 ErikE 那里得到了解决方案,并将其放入一组可用的函数中。我还在下面的函数 NCRC32 中提供了 Unicode 字符的解决方案:

    CREATE FUNCTION dbo.IndexTable
    (
          @FirstIndex           bigint
        , @LastIndex            bigint
    )
    RETURNS @Result table
    (
        Id BIGINT PRIMARY KEY
    )
    WITH SCHEMABINDING
    AS
    /***************************************************************************************************
        DESCRIPTION:
             Create an one column table of indexes starting with first specified index and 
             ending with last specified index.
    
        INPUT PARAMETERS:
             @FirstIndex:    First index to start the list of indexes with.
             @LastIndex:     Last index to end the list of indexes with.
    
        RETURN VALUE:
             Table with list of specified indexes.
    
        EXAMPLES:
            SELECT * FROM dbo.IndexTable(1, 20)
            SELECT * FROM dbo.IndexTable(1, 16)
            SELECT * FROM dbo.IndexTable(1, 17)
            SELECT * FROM dbo.IndexTable(1, 18)
            SELECT * FROM dbo.IndexTable(1, 1)
            SELECT * FROM dbo.IndexTable(1, 0)
    ***************************************************************************************************/
    BEGIN
        DECLARE @max        bigint
        ,       @offset     bigint
        ;
        IF @LastIndex IS NULL RETURN ;
        IF @FirstIndex IS NULL RETURN ;
        INSERT INTO @Result 
        VALUES  (@FirstIndex+0), (@FirstIndex+1), (@FirstIndex+2), (@FirstIndex+3), (@FirstIndex+4)
        ,       (@FirstIndex+5), (@FirstIndex+6), (@FirstIndex+7), (@FirstIndex+8), (@FirstIndex+9)
        ;
        SELECT @max= MAX(Id) FROM @Result
        ;
        WHILE @max < @LastIndex
        BEGIN
            SET @offset = (1 + @max - @FirstIndex)
            ;
            INSERT
            INTO    @Result
            SELECT  Id = Id + @offset
            FROM    @Result
            WHERE   Id <= (@LastIndex - @offset)
            ;
            SELECT @max= MAX(Id) FROM @Result
            ;
        END
        DELETE FROM @Result WHERE Id > @LastIndex
        ;
        RETURN
    END
    GO
    
    CREATE FUNCTION dbo.CRC32calc
    /***************************************************************************************************
        DESCRIPTION
            Add a byte value to a CRC calculation.
    
        INPUT PARAMETERS:
            @crc            Current CRC value.
            @byteval        Byte value to add to CRC value.
    
        RETURN VALUE:
            Resulting CRC with bytevalue added.
    
        USAGE:
            Used by functions dbo.CRC32 and dbo.NCRC32
    ***************************************************************************************************/
    (
        @crc        bigint,
        @byteval    int
    )
    RETURNS bigint
    WITH SCHEMABINDING
    AS
    BEGIN
        DECLARE @Lookup     varbinary(2048) = 0x0000000077073096EE0E612C990951BA076DC419706AF48FE963A5359E6495A30EDB883279DCB8A4E0D5E91E97D2D98809B64C2B7EB17CBDE7B82D0790BF1D911DB710646AB020F2F3B9714884BE41DE1ADAD47D6DDDE4EBF4D4B55183D385C7136C9856646BA8C0FD62F97A8A65C9EC14015C4F63066CD9FA0F3D638D080DF53B6E20C84C69105ED56041E4A26771723C03E4D14B04D447D20D85FDA50AB56B35B5A8FA42B2986CDBBBC9D6ACBCF94032D86CE345DF5C75DCD60DCFABD13D5926D930AC51DE003AC8D75180BFD0611621B4F4B556B3C423CFBA9599B8BDA50F2802B89E5F058808C60CD9B2B10BE9242F6F7C8758684C11C1611DABB6662D3D76DC419001DB710698D220BCEFD5102A71B1858906B6B51F9FBFE4A5E8B8D4337807C9A20F00F9349609A88EE10E98187F6A0DBB086D3D2D91646C97E6635C016B6B51F41C6C6162856530D8F262004E6C0695ED1B01A57B8208F4C1F50FC45765B0D9C612B7E9508BBEB8EAFCB9887C62DD1DDF15DA2D498CD37CF3FBD44C654DB261583AB551CEA3BC0074D4BB30E24ADFA5413DD895D7A4D1C46DD3D6F4FB4369E96A346ED9FCAD678846DA60B8D044042D7333031DE5AA0A4C5FDD0D7CC95005713C270241AABE0B1010C90C20865768B525206F85B3B966D409CE61E49F5EDEF90E29D9C998B0D09822C7D7A8B459B33D172EB40D81B7BD5C3BC0BA6CADEDB883209ABFB3B603B6E20C74B1D29AEAD547399DD277AF04DB261573DC1683E3630B1294643B840D6D6A3E7A6A5AA8E40ECF0B9309FF9D0A00AE277D079EB1F00F93448708A3D21E01F2686906C2FEF762575D806567CB196C36716E6B06E7FED41B7689D32BE010DA7A5A67DD4ACCF9B9DF6F8EBEEFF917B7BE4360B08ED5D6D6A3E8A1D1937E38D8C2C44FDFF252D1BB67F1A6BC57673FB506DD48B2364BD80D2BDAAF0A1B4C36034AF641047A60DF60EFC3A867DF55316E8EEF4669BE79CB61B38CBC66831A256FD2A05268E236CC0C7795BB0B4703220216B95505262FC5BA3BBEB2BD0B282BB45A925CB36A04C2D7FFA7B5D0CF312CD99E8B5BDEAE1D9B64C2B0EC63F226756AA39C026D930A9C0906A9EB0E363F720767850500571395BF4A82E2B87A147BB12BAE0CB61B3892D28E9BE5D5BE0D7CDCEFB70BDBDF2186D3D2D4F1D4E24268DDB3F81FDA836E81BE16CDF6B9265B6FB077E118B7477788085AE6FF0F6A7066063BCA11010B5C8F659EFFF862AE69616BFFD3166CCF45A00AE278D70DD2EE4E0483543903B3C2A7672661D06016F74969474D3E6E77DBAED16A4AD9D65ADC40DF0B6637D83BF0A9BCAE53DEBB9EC547B2CF7F30B5FFE9BDBDF21CCABAC28A53B3933024B4A3A6BAD03605CDD7069354DE572923D967BFB3667A2EC4614AB85D681B022A6F2B94B40BBE37C30C8EA15A05DF1B2D02EF8D
        ;
        RETURN (@crc / 256) ^ Substring(@Lookup, ((@crc & 0xFF) ^ @byteval) * 4 + 1, 4)
        ;
    END
    GO
    
    CREATE FUNCTION dbo.CRC32
    /***************************************************************************************************
        DESCRIPTION
            Compute 32-bit CRC from an ASCII character array.
    
        INPUT PARAMETERS:
            @input          ASCII text to compute CRC for.
    
        RETURN VALUE:
            Resulting 32-bit CRC value.
    
        EXAMPLES:
            SELECT  t.input, csum = CHECKSUM(t.input), t.crc, crchex = CONVERT(VARBINARY(8), t.crc)
            FROM    (   SELECT  t.input, crc = dbo.CRC32(t.input)
                        FROM    (         SELECT  input = 'test'
                                    UNION SELECT  input = 'x'
                                    UNION SELECT  input = ''
                                    UNION SELECT  input = NULL
                                    UNION SELECT  input = 'stop'
                                    UNION SELECT  input = 'pots'
                                    UNION SELECT  input = 'System.IO.Stream'
                                    UNION SELECT  input = 'SYSTEM.IO.Stream'
                                    UNION SELECT  input = 'Test.fqn.data'
                                    UNION SELECT  input = 'Test.fqn.datax'
                                ) AS t
                    ) AS t
    ***************************************************************************************************/
    (
        @input varchar(max)
    )
    RETURNS int
    WITH SCHEMABINDING
    AS
    BEGIN
        DECLARE @crc        bigint = 0xFFFFFFFF
        ,       @result     int
        ;
        SELECT @crc = dbo.CRC32calc(@crc, Ascii(Substring(@input, v.id, 1)))
        FROM    dbo.IndexTable(1, LEN(@input)) AS v
        ORDER
        BY      v.Id
        ;
        SET @result = CONVERT(int, CONVERT(VARBINARY(4), ~@crc)) ;
        RETURN @result ;
    END
    GO
    
    CREATE FUNCTION dbo.NCRC32
    /***************************************************************************************************
        DESCRIPTION
            Compute 32-bit CRC from a UNICODE character array.
    
        INPUT PARAMETERS:
            @input          ASCII text to compute CRC for.
    
        RETURN VALUE:
            Resulting 32-bit CRC value.
    
        EXAMPLES:
            SELECT  t.input, csum = CHECKSUM(t.input), t.crc, crchex = CONVERT(VARBINARY(8), t.crc)
            FROM    (   SELECT  t.input, crc = dbo.NCRC32(t.input)
                        FROM    (         SELECT  input = N'test'
                                    UNION SELECT  input = N'x'
                                    UNION SELECT  input = N''
                                    UNION SELECT  input = NULL
                                    UNION SELECT  input = 'stop'
                                    UNION SELECT  input = 'pots'
                                    UNION SELECT  input = N'System.IO.Stream'
                                    UNION SELECT  input = N'SYSTEM.IO.Stream'
                                    UNION SELECT  input = N'Test.fqn.data'
                                    UNION SELECT  input = N'Test.fqn.datax'
                                ) AS t
                    ) AS t
    ***************************************************************************************************/
    (
        @input nvarchar(max)
    )
    RETURNS int
    WITH SCHEMABINDING
    AS
    BEGIN
        DECLARE @crc        bigint = 0xFFFFFFFF
        ,       @result     int
        ;
        SELECT  @crc = dbo.CRC32calc( dbo.CRC32calc(@crc, (cval / 256)), cval & 0xFF)
        FROM    (   SELECT  v.id, cval = UNICODE(SUBSTRING(@input, v.id, 1))
                    FROM    dbo.IndexTable(1, LEN(@input)) AS v
                ) AS t
        ORDER
        BY      t.Id
        ;
        SET @result = CONVERT(int, CONVERT(VARBINARY(4), ~@crc)) ;
        RETURN @result ;
    END
    GO
    

    【讨论】:

      【解决方案4】:

      我不认为 T-SQL 让您可以选择使用正确的 CRC 作为校验和函数。仅供参考,SQL Server 集成服务 (SSIS) 确实有一个“校验和”转换,让您可以选择要使用的校验和算法,其中一个选择是:

      CRC32 - 使用标准的 32 位循环 冗余校验(CRC),这提供 更开放的实现。

      要在 SQL 中实现 CRC,您可以编写 CRC 的纯 T-SQL 实现(有趣!),或者(如果您使用 SQL Server 2005 或更高版本)用另一种 .NET 语言编写/查找它,然后然后将该类用作已编译的 SQL 存储过程。

      【讨论】:

        【解决方案5】:

        这是一个教育练习,还是您需要在应用程序中实际使用它。如果是第二种,我建议您在应用程序而不是 SQL Server 中执行此操作。如果有替代方法,任何可用的方法,即使是使用 CLR,也可能会更有效,风险更大。大多数选项都会影响 SS 性能。

        如果你需要它来验证输入,那么加载它的模块应该在加载时检查(并且可能设置一个状态列。)如果你需要它来输出并且不容易动态计算它,那么让输入模块计算并存储在列中。

        如果您想使用它来验证列没有损坏,那么有更好的方法来处理不太可能出现的问题,或者您有一个不稳定的服务器需要处理。

        【讨论】:

          【解决方案6】:

          这是从上面的原始代码帖子派生的非基于表格的解决方案。专家们将不得不权衡这是否比基于表格的解决方案更有效。我的想法是,如果您计算 1,000 条记录的校验和,其中 1 行字符数为 1,000 个字符,那么您对 ​​CRC 查找表执行了 1,000,000 次选择命中,这不会比内存计算更有效.也许是的。

          Declare @input as varchar(1000) 
          Set @input='This is the CRC test' 
          Declare @CRCtable as varchar(3080)   --Location of Edit
          Declare @Index as int  
          Declare @crc as BIGINT 
          Declare @length as INT 
          Declare @i as INT 
          Declare @tblval as BIGINT  
          Declare @CTindex as int 
          Declare @ans as varchar(25) 
          
          Set @CRCtable='0000000000, 1996959894, 3993919788, 2567524794, 0124634137, 1886057615, 3915621685, 2657392035, 0249268274, 2044508324, 3772115230, 2547177864, 0162941995, 2125561021, 3887607047, 2428444049, 0498536548, 1789927666, 4089016648, 2227061214, 0450548861, 1843258603, 4107580753, 2211677639, 0325883990, 1684777152, 4251122042, 2321926636, 0335633487, 1661365465, 4195302755, 2366115317, 0997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 0901097722, 1119000684, 3686517206, 2898065728, 0853044451, 1172266101, 3705015759, 2882616665, 0651767980, 1373503546, 3369554304, 3218104598, 0565507253, 1454621731, 3485111705, 3099436303, 0671266974, 1594198024, 3322730930, 2970347812, 0795835527, 1483230225, 3244367275, 3060149565, 1994146192, 0031158534, 2563907772, 4023717930, 1907459465, 0112637215, 2680153253, 3904427059, 2013776290, 0251722036, 2517215374, 3775830040, 2137656763, 0141376813, 2439277719, 3865271297, 1802195444, 0476864866, 2238001368, 4066508878, 1812370925, 0453092731, 2181625025, 4111451223, 1706088902, 0314042704, 2344532202, 4240017532, 1658658271, 0366619977, 2362670323, 4224994405, 1303535960, 0984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 0879679996, 2909243462, 3663771856, 1141124467, 0855842277, 2852801631, 3708648649, 1342533948, 0654459306, 3188396048, 3373015174, 1466479909, 0544179635, 3110523913, 3462522015, 1591671054, 0702138776, 2966460450, 3352799412, 1504918807, 0783551873, 3082640443, 3233442989, 3988292384, 2596254646, 0062317068, 1957810842, 3939845945, 2647816111, 0081470997, 1943803523, 3814918930, 2489596804, 0225274430, 2053790376, 3826175755, 2466906013, 0167816743, 2097651377, 4027552580, 2265490386, 0503444072, 1762050814, 4150417245, 2154129355, 0426522225, 1852507879, 4275313526, 2312317920, 0282753626, 1742555852, 4189708143, 2394877945, 0397917763, 1622183637, 3604390888, 2714866558, 0953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 0906185462, 1090812512, 3747672003, 2825379669, 0829329135, 1181335161, 3412177804, 3160834842, 0628085408, 1382605366, 3423369109, 3138078467, 0570562233, 1426400815, 3317316542, 2998733608, 0733239954, 1555261956, 3268935591, 3050360625, 0752459403, 1541320221, 2607071920, 3965973030, 1969922972, 0040735498, 2617837225, 3943577151, 1913087877, 0083908371, 2512341634, 3803740692, 2075208622, 0213261112, 2463272603, 3855990285, 2094854071, 0198958881, 2262029012, 4057260610, 1759359992, 0534414190, 2176718541, 4139329115, 1873836001, 0414664567, 2282248934, 4279200368, 1711684554, 0285281116, 2405801727, 4167216745, 1634467795, 0376229701, 2685067896, 3608007406, 1308918612, 0956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 0936918000, 2847714899, 3736837829, 1202900863, 0817233897, 3183342108, 3401237130, 1404277552, 0615818150, 3134207493, 3453421203, 1423857449, 0601450431, 3009837614, 3294710456, 1567103746, 0711928724, 3020668471, 3272380065, 1510334235, 0755167117, '
          Set @crc = 0xFFFFFFFF  
          Set @length = LEN(@input)  
          Set @i = 1  
          
          While @i <= @length  
            Begin  
            Set @index = ((@crc & 0xff) ^ ASCII(SUBSTRING(@input, @i, 1)))        
            Set @CTindex = (@index * 12) + 1
            Set @ans=substring(@CRCtable,@CTindex,10  )  
            Set @tblval = convert(bigint,@ans) 
            Set @crc = (@crc / 256) ^ @tblval     
            Set @i = @i + 1       
            End  
          Set @crc = ~@crc  
          
          SELECT @crc as CRC32, CONVERT(VARBINARY(4), @crc) as CRC32Hex
          

          【讨论】:

          • 不幸的是,这并不总是给出正确的结果。此字符串不起作用“schemenewbusiness/ACM0025/S100/default.aspx”。
          • 找到了,@CRCtable需要是varchar(3080)
          • 为什么在不需要分隔符时使用它们?为什么要使用字符串?与数字数据类型相比,字符串转换和操作非常慢。
          • 另外,查找表是一个表变量,因此可能适合内存。但是现在看看我的回答。
          【解决方案7】:

          SQL 2005 及之后的版本具有函数CHECKSUMCHECKSUM_AGG。这类似于 CRC,可能适用于哈希表或快速检查更改的数据。 CHECKSUM(*) 将返回一个包含单行所有列的值。

          我对其进行了简单的测试,它对字符串上的大小写和尾随空格不敏感。如果带有前导或嵌入的空白,它确实会改变。值的顺序很重要。

          【讨论】:

            猜你喜欢
            • 2017-03-01
            • 2011-11-08
            • 2021-08-09
            • 1970-01-01
            • 1970-01-01
            • 2014-07-27
            • 2019-09-27
            • 2011-09-23
            • 2018-03-11
            相关资源
            最近更新 更多