2011-12-25 3 views
3

Мне нужно заменить несколько разные слова в текстовом поле.MySQL: используя ЗАМЕНИТЬ С ПРИСОЕДИНЕНИЕМ?

Значения поиска и замены находятся в другой таблице.

Например, тексты-таблица:

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

я ушел из условия, потому что я не знаю, как определить это, и до сих пор не знаю. Если я использую CROSS JOIN (без условия), с 2 записями в text_table, то как-то заменяется только LAST-слово в записи LAST. – Dylan

+0

@Dylan Вам нужно указать предложение join на основе структуры ваших таблиц и данных, которые вы хотите выбрать, чтобы обновить его, 'CROSS JOIN' объединит каждую строку из первой таблицы с каждой строкой из второй таблицы, так что вы получили декартово произведение строк из двух таблиц, поэтому я думаю, что это не сработает для вас. поэтому попробуйте использовать левое соединение или другие объединения. –

0

A JOIN - неправильный подход. Результирующие строки JOIN создаются объединением отдельных строк из каждой объединенной таблицы. Это не подходит для того, что вы хотите сделать. Для SELECT, JOIN в сочетании с GROUP BY будет иметь немного больше смысла, хотя нет GROUP BY в UPDATE, так что это не вариант.

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 
; 
Смежные вопросы