zoukankan      html  css  js  c++  java
  • 【Teradata UDF】中文按字符查找chs_instr

    一.场景描述

    数据库为ASCII编码单字节存储,在查询中文时可能会出现错误结果。例如查询like“房”字,会查询出不含“房”,含“朔科”的结果。

    select * from Tablename01 where name like '%房%';

    二.原因分析

     一个汉字为2个字符,“朔”的第二个字节与“科”的第一个字节,正好与“房”的两个字节相同。查看十六进制,如下:

    select  char2hexint('');  --00B7 00BF
    select char2hexint('朔科'); --00CB 00B7 00BF 00C6

    三.解决方案

     1.安装部署自定义函数chs_instr

             chs_instr(参数1,参数2)是一个C编写的自定义函数,它的功能是在参数1中查找参数2,按照参数2的字节数去查找,如果查询不到则返回0,查询到则返回大于0的值。

             经查在Teradata库中,使用此UDF函数与like比较,IO数基本不变,CPUTime突增近100倍。所以,遇到此类问题时,优先考虑从设计层面规避like中文。

    2.语句【name like ‘%房%’】替换成【chs_instr(name,'房')>0】

    四.UDF安装部署

    Teradata支持C语言的自定义函数。具体部署方法如下:

    1、如下UDF存储到文件中,文件名称为chs_instr.udf

    /*
    database syslib;
    replace FUNCTION chs_instr(srcStr VARCHAR(1024), childStr VARCHAR(64)) 
    RETURNS INTEGER 
    LANGUAGE C 
    NO SQL 
    PARAMETER STYLE TD_GENERAL 
    EXTERNAL NAME chs_instr;
    sel chs_instr('弢1234|', '|');
    sel index('弢1234|', '|');
    */

    2、如下为UDF定义中引用的C函数,文件名称为chs_instr.c

    #define SQL_TEXT Latin_Text
    #include <sqltypes_td.h>
    #include <string.h>
    /* Result is 0, if search_str does not apper in source_string               */
    /*        index, a pos(start at 1) to the firt occurrence of search_str of source_string */
    void chs_instr(VARCHAR_LATIN *source_string,VARCHAR_LATIN *search_str,
      int *result,
      char sqlstate[6])
    {
        unsigned char *src = source_string, *sub = search_str, c;
      int sublen = strlen(sub);
        int slen = strlen(src);
        int spos = 0;
        *result = 0;
        while ( spos <= slen-sublen ) {
        if (memcmp(src+spos, sub, sublen) == 0) { 
          *result = spos+1; 
          break; 
        }
            c = src[spos++];
            if (c > 128) spos++;
        }
        return;
    }

    3、使用bteq登录数据库(dbc用户),指定UDF默认存储数据库为syslib。

    bteq "logon citic/dbc,dbc" < chs_instr.udf

     附录:memcmp函数是按字节比较的。

    s1,s2为字符串时候memcmp(s1,s2,1)就是比较s1和s2的第一个字节的ascII码值;
    memcmp(s1,s2,n)就是比较s1和s2的前n个字节的ascII码值;
    如:char *s1="abc";
    char *s2="acd";
    int r=memcmp(s1,s2,3);
    就是比较s1和s2的前3个字节,第一个字节相等,第二个字节比较中大小已经确定,不必继续比较第三字节了。所以r=-1.

  • 相关阅读:
    ant desigon Upload控件能否提供隐藏删除图标的属性以及鼠标停留在删除图标上的提示文字怎么设置为中文
    2月5日进度
    2月4日学习进度
    2月3日学习进度
    2月2日学习进度
    大数据之linux环境下jdk hadoop以及hbase,hive等配置
    MVC实例
    MVC简介
    23种设计模式
    xxx系统可用性和易用性分析
  • 原文地址:https://www.cnblogs.com/badboy200800/p/9784654.html
Copyright © 2011-2022 走看看