2011-12-25 116 views
3

我需要在文本字段中替換多個不同的單詞。MySQL:使用REPLACE加入?

搜索和替換值位於另一個表中。

例如文本表是:

The Quick Brown Fox 
The Dirty Red Bandana 

與替換表是這樣的:那麼

SearchValue   ReplaceValue 
    Quick    Slow 
    Fox     Wolf 
    Dirty    Clean 
    Bandana    Hat 

被替換的記錄將成爲:

The Slow Brown Wolf 
The Clean Red Hat 

是它可以用JOIN做到這一點?

喜歡的東西:

UPDATE texts_table AS tt 
CROSS JOIN values_table AS vt 
SET tt.Text= REPLACE(tt.Text, vt.SearchValue, vt.ReplaceValue) 

我嘗試了一些不同的方法,但不能得到它來代替所有字符串文本字段。

回答

2

你需要指定一個加入條件,例如,像這樣:

UPDATE texts_table AS tt 
INNER JOIN values_table AS vt 
    on tt.valueId = vt.valudId /*or whatever the join condition*/ 
SET tt.Text= REPLACE(tt.Text, vt.SearchValue, vt.ReplaceValue) 

UPDATE從句的語法定義:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference 

的table_references子句列出的表參與加入。其語法描述爲JOIN Syntax

+0

我離開了ON狀態,因爲我不知道如何指定它,還是不知道。如果我使用CROSS JOIN(沒有條件),在texts_table中有兩條記錄,不知何故,只有最後一條記錄中的最後一個字被替換。 – Dylan 2011-12-25 10:57:09

+0

@Dylan您需要根據表結構指定join子句以及要更新它的數據,'CROSS JOIN'會將第一個表中的每一行與第二個表中的每一行結合起來你從兩張表中獲得了行的笛卡爾積,所以我認爲這對你不起作用。所以請嘗試使用左連接或其他連接。 – 2011-12-25 15:42:27

0

A JOIN是錯誤的方法。 JOIN的結果行通過組合每個連接表中的單個行來創建。這不符合你想要做的事情。對於SELECTJOIN加上GROUP BY會更有意義,但UPDATE中沒有GROUP BY子句,所以這不是一個選項。

SQL不適用於這種文本操作。它應該由編程語言來執行,而不是數據語言。

對於SELECT,你可能會迫使SQL做的工作寫一個user definedaggregate功能,喜歡的東西:

/** 
* make_string: Strings hold both character sequence and a length. Strings can 
* hold null characters and are null terminated for safety, in case they hold 
* C-strings, but the null character shouldn't be used as a terminator by any 
* string function. 
* 
* @param data: characters to copy to string 
* @param len: number of characters to copy from data 
* @param size: number of characters to allocate; lets you allocate extra space. 
*  If size < len, size is set to len, so you can pass 0 to not allocate 
*  extra space. 
*/ 
string_t* make_string(const char *data, int len, int size); 
string_t* delete_string(string_t* str); 
char* string_data(string_t* str); 
int string_length(string_t* str); 
/** 
* Copy data to str's buffer, replacing whatever was stored there previously. 
* 
* @returns 0 on success, non-0 on failure. 
*/ 
int string_set(string_t* str, const char* data, int len); 
/** 
* Replace first occurrence of 'search' in 'str' with 'replace', starting the 
* search at character 'start'. 
* 
* If there isn't enough space in str's buffer, resize the buffer. If there is 
* enough space, must always succeed. 
* 
* @returns position of character after replaced section, or -1 if search isn't found. 
*/ 
int string_replace(string_t* str, string_t* search, string_t* replace, int start); 
... 

my_bool group_replace_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 
    if (args->arg_count != 3) { 
     strcpy(message,"wrong argument count: group_replace(str, search, replacement) requires three string arguments"); 
     return 1; 
    } 
    initid->maybe_null = 1; 
    initid->max_length = args->lengths[0]; 
    if (! (initid->ptr = make_string("", 0, args->lengths[0]))) { 
     snprintf(message, MYSQL_ERRMSG_SIZE, "error allocating string for group_replace: %s", strerror(errno)); 
     return 1; 
    } 
    return 0; 
} 

void group_replace_deinit(UDF_INIT *initid) { 
    delete_string(initid->ptr); 
} 

void group_replace_clear(UDF_INIT *initid, char *is_null, char *error) { 
    string_set(initid->ptr, "", 0); 
    // result will be null, until 
    *is_null = 1; 
    *error = 0; 
} 

void group_replace_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 
    if (*error) { 
     return; 
    } 
    if (*is_null && args->args[0]) { 
     if (string_set(initid->ptr, args->args[0], args->lengths[0])) { 
      *error = 1; 
      return; 
     } 
     *is_null = 0; 
    } 
    string_t *search, *replacement; 
    if (! (search = make_string(args->args[1], args->lengths[1]))) { 
     *error = 1; 
     return; 
    } 
    if (! (replacement = make_string(args->args[2], args->lengths[2]))) { 
     delete_string(search); 
     *error = 1; 
     return; 
    } 
    int pos=0; 
    do { 
     pos = string_replace(initid->ptr, search, replacement, pos); 
    } while (0 <= pos); 
} 
char* group_replace(UDF_INIT *initid, UDF_ARGS *args, 
        char *result, unsigned long *length, 
        char *is_null, char *error) 
{ 
    if (*is_null) { 
     *length = 0; 
     return null; 
    } 
    *length = string_length(initd->ptr); 
    return string_data(initid->ptr); 
} 

以上:

  • 是未經測試。
  • 將(大概)區分大小寫(取決於您如何實現string_replace),這與MySQL的其他字符串函數的行爲不同。對於不區分大小寫,請執行並使用string_ireplace函數。

將字符串函數的實現留作練習。

相應SELECT語句應該是:

SELECT tt.id, GROUP_REPLACE(tt.Text, vt.SearchValue, vt.ReplaceValue) 
    FROM texts_table AS tt 
    JOIN values_table AS vt ON INSTR(tt.Text, vt.SearchValue) > 0 
    GROUP BY tt.id 
;