在SQL中使用CLR提供基本函数对二进制数据进行解析与构造

?

二进制数据包的解析一般是借助C#等语言,在通讯程序中解析后形成字段,再统一单笔或者批量(表类型参数)提交至数据库,在通讯程序中,存在BINARY到struct再到table的转换。

现借助CLR提供基本的INT2HEX(小端)等函数,在SQL中直接解析数据包。

?

基本函数

  1. [Microsoft.SqlServer.Server.SqlFunction(Name = "Time2UTCBin")]
  2. public
    static SqlBinary Time2UTCBin(DateTime time)
  3. {
  4. ????return
    new SqlBinary(BitConverter.GetBytes((uint)(MyTime.ConverDateTimeToJavaMilliSecond(time) / 1000)));
  5. }
  6. [Microsoft.SqlServer.Server.SqlFunction(Name = "UTCBin2Time")]
  7. public
    static SqlDateTime UTCBin2Time(byte[] data,int offset)
  8. {
  9. ????return
    new SqlDateTime(MyTime.ConverDateTimeFromJavaMilliSecond(BitConverter.ToUInt32(data, offset) * 1000L));
  10. }
  11. ?
  12. [Microsoft.SqlServer.Server.SqlFunction(Name = "getSum")]
  13. public
    static SqlByte Sum(byte[] buffer, int startPos, int endPos)
  14. {
  15. ????byte b = 0;
  16. ????for (int i = startPos; i <= endPos; i++)
  17. ????{
  18. ????????b ^= buffer[i];
  19. ????}
  20. ????return b;
  21. }
  22. ?
  23. [Microsoft.SqlServer.Server.SqlFunction(Name = "updateSum")]
  24. public
    static SqlBinary updateSum(byte[] buffer, int startPos, int endPos, int sumPos)
  25. {
  26. ????byte b = 0;
  27. ????for (int i = startPos; i <= endPos; i++)
  28. ????{
  29. ????????b ^= buffer[i];
  30. ????}
  31. ????buffer[sumPos] = b;
  32. ????return
    new SqlBinary(buffer);
  33. }
  34. ?
  35. ?
  36. [Microsoft.SqlServer.Server.SqlFunction(Name = "Int2Bin")]
  37. public
    static SqlBinary Int2Bin(int number)
  38. {
  39. ????return
    new SqlBinary(BitConverter.GetBytes(number));
  40. }
  41. ?
  42. [Microsoft.SqlServer.Server.SqlFunction(Name = "Long2Bin")]
  43. public
    static SqlBinary Long2Bin(long number)
  44. {
  45. ????return
    new SqlBinary(BitConverter.GetBytes(number));
  46. }
  47. [Microsoft.SqlServer.Server.SqlFunction(Name = "Bin2Int")]
  48. public
    static SqlInt32 Bin2Int(byte[] data, int offset)
  49. {
  50. ????return
    new SqlInt32(BitConverter.ToInt32(data,offset));
  51. }
  52. [Microsoft.SqlServer.Server.SqlFunction(Name = "Bin2Long")]
  53. public
    static SqlInt64 Bin2Long(byte[] data, int offset)
  54. {
  55. ????return
    new SqlInt64(BitConverter.ToInt64(data, offset));
  56. }
  57. [Microsoft.SqlServer.Server.SqlFunction(Name = "getByte")]
  58. public
    static SqlByte getByte(byte[] data, int offset)
  59. {
  60. ????return
    new SqlByte(data[offset]);
  61. }
  62. [Microsoft.SqlServer.Server.SqlFunction(Name = "getBytes")]
  63. public
    static SqlBytes getBytes(byte[] data, int offset,int count)
  64. {
  65. ????byte[] temp = new
    byte[count];
  66. ????Array.Copy(data, offset, temp, 0, count);
  67. ????return
    new SqlBytes(temp);
  68. }

?

?

数据包的结构体(表类型)

  1. --交易扩展记录
  2. CREATE TYPE [dbo].[DeviceTranscationEMV] AS
    TABLE
  3. (
  4. [RawData] VARBINARY(200) NOT
    NULL,
  5. [DeviceID] UNIQUEIDENTIFIER
    NOT
    NULL,
  6. [EMVType] TINYINT
    NOT
    NULL,
  7. [EMVNO] SMALLINT
    NOT
    NULL,
  8. [HardwareNo] INT
    NOT
    NULL,
  9. Meter INT,
  10. run INT,
  11. WORK
    INT,
  12. dead INT,
  13. StartTime DATETIME ,
  14. EndTime DATETIME
  15. )

?

?

SQL中借助CLR实现的转换函数

?

  1. CREATE
    FUNCTION [dbo].[Binary2EMVTaxi]
  2. ????(
  3. [email protected] VARBINARY(MAX) ,
  4. [email protected] INT = 1 ,
  5. [email protected] BIT = 0
  6. ????)
  7. RETURNS @emv TABLE
  8. ????(
  9. ??????[RawData] BINARY(72) NOT
    NULL ,
  10. ??????[DeviceID] UNIQUEIDENTIFIER ,
  11. ??????[EMVType] TINYINT
    NOT
    NULL ,
  12. ??????[EMVNO] SMALLINT
    NOT
    NULL ,
  13. ??????[HardwareNo] INT
    NOT
    NULL ,
  14. ??????Meter INT ,
  15. ??????run INT ,
  16. ??????WORK
    INT ,
  17. ??????dead INT ,
  18. ??????StartTime DATETIME ,
  19. ??????EndTime DATETIME
  20. ????)
  21. AS
  22. ????BEGIN
  23. ????????DECLARE @c INT
  24. ????????DECLARE @size
    INT
  25. ????????DECLARE @sized INT
  26. ?
  27. ????????IF @withdeviceid = 1
  28. ????????????BEGIN
  29. ????????????????SET @sized = 16
  30. ????????????????SET @size = 72 + @sized
  31. ????????????END
  32. ????????ELSE
  33. ????????????BEGIN
  34. ????????????????SET @sized = 0
  35. ????????????????SET @size = 72
  36. ????????????END
  37. ?
  38. ????????SET @c = DATALENGTH(@data) / @size;
  39. ?
  40. ????????WITH sub
  41. ??????????????????AS ( SELECT
    SUBSTRING(@data, 1 + id * @size + @offset,
  42. [email protected]size) binDATA
  43. ???????????????????????FROM sys_id
  44. ???????????????????????WHERE id < @c
  45. ?????????????????????)
  46. ????????????INSERT @emv
  47. ????????????????????( rawdata ,
  48. ??????????????????????DeviceID ,
  49. ??????????????????????hardwareno ,
  50. ??????????????????????meter ,
  51. ??????????????????????run ,
  52. ??????????????????????WORK ,
  53. ??????????????????????dead ,
  54. ??????????????????????starttime ,
  55. ??????????????????????endtime ,
  56. ??????????????????????emvtype ,
  57. ??????????????????????emvno
  58. ????????????????????)
  59. ????????????????????SELECT
    CASE @withDeviceID
  60. ??????????????????????????????WHEN 0 THEN bindata
  61. ??????????????????????????????ELSE
    SUBSTRING(bindata, 1 + @sized, @size)
  62. ????????????????????????????END ,
  63. ????????????????????????????CASE @withDeviceID
  64. ??????????????????????????????WHEN 0 THEN
    NULL
  65. ??????????????????????????????ELSE
    CAST (SUBSTRING(bindata, 1, @sized) AS
    UNIQUEIDENTIFIER)
  66. ????????????????????????????END ,
  67. ????????????????????????????dbo.Bin2Int(bindata, 0 + @sized) RecordNo ,
  68. ????????????????????????????dbo.Bin2Int(bindata, 4 + @sized) Meter ,
  69. ????????????????????????????dbo.Bin2Int(bindata, 8 + @sized) run ,
  70. ????????????????????????????dbo.Bin2Int(bindata, 12 + @sized) WORK ,
  71. ????????????????????????????dbo.Bin2Int(bindata, 16 + @sized) dead ,
  72. ????????????????????????????dbo.utcbin2time(bindata, 20 + @sized) StartTime ,
  73. ????????????????????????????dbo.utcbin2time(bindata, 24 + @sized) EndTime ,
  74. ????????????????????????????dbo.getByte(bindata, 61 + @sized) RecordType ,
  75. ????????????????????????????dbo.getByte(bindata, 62 + @sized) EMVNo
  76. ????????????????????FROM sub
  77. ????????RETURN
  78. ????END

?

  1. CREATE
    FUNCTION [dbo].[EMVTaxi2Binary]
  2. ????(
  3. [email protected] DeviceTranscationEMV READONLY ,
  4. [email protected] BIT = 0
  5. ????)
  6. RETURNS
    VARBINARY(MAX)
  7. AS
  8. ????BEGIN
  9. ????????DECLARE @bin VARBINARY(MAX)
  10. ????????SET @bin = 0x0
  11. ????????IF @withDeviceID = 0
  12. ????????????SELECT @bin = @bin + dbo.updatesum(dbo.int2Bin([HardwareNo])
  13. ????????????????????????????????????????????????+ dbo.int2Bin(meter)
  14. ????????????????????????????????????????????????+ dbo.int2Bin(run)
  15. ????????????????????????????????????????????????+ dbo.int2Bin(work)
  16. ????????????????????????????????????????????????+ dbo.int2Bin(dead)
  17. ????????????????????????????????????????????????+ dbo.time2utcbin(starttime)
  18. ????????????????????????????????????????????????+ dbo.time2utcbin(endtime)
  19. ????????????????????????????????????????????????+ CAST(0 AS
    BINARY(33))
  20. ????????????????????????????????????????????????+ CAST(emvtype AS
    BINARY(1))
  21. ????????????????????????????????????????????????+ CAST(emvno AS
    BINARY(1))
  22. ????????????????????????????????????????????????+ CAST (0 AS
    BINARY(1))
  23. ????????????????????????????????????????????????+ CAST(0 AS
    BINARY(7)) + 0x55,
  24. ????????????????????????????????????????????????0, 62, 63)
  25. ????????????FROM @emv
  26. ?
  27. ????????ELSE
  28. ????????????SELECT @bin = @bin + CAST (deviceid AS
    BINARY(16))
  29. ????????????????????+ dbo.updatesum(dbo.int2Bin([HardwareNo])
  30. ????????????????????????????????????+ dbo.int2Bin(meter) + dbo.int2Bin(run)
  31. ????????????????????????????????????+ dbo.int2Bin(work) + dbo.int2Bin(dead)
  32. ????????????????????????????????????+ dbo.time2utcbin(starttime)
  33. ????????????????????????????????????+ dbo.time2utcbin(endtime)
  34. ????????????????????????????????????+ CAST(0 AS
    BINARY(33))
  35. ????????????????????????????????????+ CAST(emvtype AS
    BINARY(1))
  36. ????????????????????????????????????+ CAST(emvno AS
    BINARY(1))
  37. ????????????????????????????????????+ CAST (0 AS
    BINARY(1))
  38. ????????????????????????????????????+ CAST(0 AS
    BINARY(7)) + 0x55, 0, 62, 63)
  39. ????????????FROM @emv
  40. ?
  41. ????????RETURN @bin
  42. ????END

?

?

测试代码

?

  1. PRINT N‘构造EMV数据,转换为BIN,然后再转换回EMV数据‘
  2. go
  3. DECLARE @emv DeviceTranscationEMV
  4. WITH data
  5. ??????????AS ( SELECT id RecordNo ,
  6. ????????????????????????15 Meter ,
  7. ????????????????????????100 run ,
  8. ????????????????????????80 WORK ,
  9. ????????????????????????20 dead ,
  10. ????????????????????????DATEADD(s, id, ‘2014-9-1 12:50:01‘) StartTime ,
  11. ????????????????????????DATEADD(mi, id, ‘2014-9-1 13:23:11‘) EndTime ,
  12. ????????????????????????4 RecordType ,
  13. ????????????????????????0 EMVNo
  14. ???????????????FROM dbo.Sys_ID
  15. ???????????????WHERE id < 100
  16. ?????????????)
  17. ????INSERT
    INTO @emv
  18. ????????????( rawdata ,
  19. ??????????????deviceid ,
  20. ??????????????emvtype ,
  21. ??????????????emvno ,
  22. ??????????????hardwareno ,
  23. ??????????????meter ,
  24. ??????????????run ,
  25. ??????????????work ,
  26. ??????????????dead ,
  27. ??????????????starttime ,
  28. ??????????????endtime
  29. ????????????)
  30. ????????????SELECT 0x00 ,
  31. ????????????????????NEWID() ,
  32. ????????????????????recordtype ,
  33. ????????????????????emvno ,
  34. ????????????????????recordno ,
  35. ????????????????????meter ,
  36. ????????????????????run ,
  37. ????????????????????work ,
  38. ????????????????????dead ,
  39. ????????????????????starttime ,
  40. ????????????????????EndTime
  41. ????????????FROM data
  42. SELECT *
  43. FROM @emv
  44. DECLARE @data VARBINARY(MAX)
  45. ?
  46. SELECT @data = dbo.emvtaxi2binary(@emv, 1)
  47. PRINT @data
  48. ?
  49. ?
  50. SELECT *
  51. FROM dbo.binary2emvtaxi(@data, 1, 1)

?

?

执行结果:

?

?

?

?

资源:

?

?

?

?

时间: 2024-10-25 16:51:48

在SQL中使用CLR提供基本函数对二进制数据进行解析与构造的相关文章

sql中的 where 、group by 和 having 用法解析(摘抄)

文章地址来源: https://www.cnblogs.com/gqs92/archive/2017/04/26/6767973.html --sql中的 where .group by 和 having 用法解析 --如果要用到group by 一般用到的就是"每这个字" 例如说明现在有一个这样的表:每个部门有多少人 就要用到分组的技术 select DepartmentID as '部门名称',COUNT(*) as '个数' from BasicDepartment group

sql中如何 将一张表的数据 更新到另外一张表的字段中

今天操作数据库       有个需求需要从一张流水表中有用户付款金额    还有一张  是用户的结算金额    每个用户的付款和结算费率和手续费等都不一样   需要将剩余可以结算的金额查询出来  进行更新到各自对应的用户后面  花了几分钟写出来去测试了一下  没问题 万变不离其中   依然还是  在 update  +表(及其关联表) +set  +更改字段 +where 条件 update merchant m join ( select pc.cp_channel channelId,0.0

SQL中char nchar varchar nvarchar text ntext的区别

类型 长度 使用说明 长度说明 char(n) 定长 索引效率高,程序里面使用trim去除多余的空白 n必须是一个介于1和8000之间的数值,存储大小为n个字节 varchar(n) 变长 效率没char高 灵活 n必须是一个介于1和8000之间的数值.存储大小为输入数据的字节的实际长度,而不是n个字节 text(n) 变长 非Unicode数据 不用指定长度 nchar(n) 定长 处理Unicode数据类型(所有的字符使用两个字节表示) n的值必须介于1和4000之间,存储大小为n字节的两倍

【SQL】SQL中笛卡尔积、内连接、外连接的数据演示

SQL的查询语句中,常使用到内连接.外连接,以及连接的基础--笛卡尔积运算. 在简单的SQL中,也许我们还分辨清楚数据如何连接,一旦查询复杂了,脑子也犯浆糊了,迷迷糊糊的. 本文,简单以数据形式记录连接的数据结果,在迷糊时可翻阅. 以MySQL运行. > 原始的表 select * from t_user u; select * from t_address a; select * from t_phone p; > 笛卡尔积 select * from t_user, t_address;

SQL中的float类型的数据

问题1.  如何在SQL中默认的使用float类型的数据 SQL中想要通过计算的方式最快的得到一个float类型的数据,只需要运算的其中一个值后面加上小数点就ok. 比如 :9/2=4 但是 :9/2.0=4.50000 问题2.  如何截取字段,只保留小数点两位 convert(float,4.50000,2) 原文地址:https://www.cnblogs.com/wangjinya/p/9900939.html

SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数

原文:SQL Server中的CLR编程--用.NET为SQL Server编写存储过程和函数 很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程.触发器和存储过程的,不过之前开发的系统要么因为历史原因用的是SQL2000要么根本用不着在SQL Server中启用CLR,所以一直没有尝试.最近因为项目的原因,在这方面做了一个调研,现在在这里分享一下心得. 首先要说明的是要在SQL Server中启用CLR必须是在SQL Server2005及以上版本,其次在默认情况下是

在SQL中使用自定义函数

  由于数据库的一个表字段中多包含html标签,现在需要修改数据库的字段把html标签都替换掉.当然我可以通过写一个程序去修改,那毕竟有点麻烦.直接在查询分析器中执行,但是MS SQL Server并没有提供正则表达式,替换html标签可不那么容易.我们可以通过CLR托管来实现一个通过正则表达式来替换html标签的自定义函数.(注:SQL CLR只能在MS SQL Server 2005或以上版本中适用) 第一步:通过Visual Studio 2008新建一个SQL Server项目 第二步:

Sql Server 与CLR集成

.NET编程和SQL Server ——Sql Server 与CLR集成 一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数等十分有限,经常需要外部的代码来执行一些繁重的移植: 2.与CLR集成可将原本需要独立的程序来实现的功能迁移到SQL Server 内部进行数据操作: 3.T-SQL数据查询语言在返回数据集方面很好,但是除此之外表现不佳.与CLR的集成可解决这一问题: 4..NET的操作代码和执行的速度比T-SQL快的很多..NET程序是已经

SQL中使用WITH AS提高性能,使用公用表表达式(CTE)简化嵌套SQL

一.WITH AS的含义     WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分. 特别对于UNION ALL比较有用.因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可.如果WITH AS短语所定