【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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM