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
;
я ушел из условия, потому что я не знаю, как определить это, и до сих пор не знаю. Если я использую CROSS JOIN (без условия), с 2 записями в text_table, то как-то заменяется только LAST-слово в записи LAST. – Dylan
@Dylan Вам нужно указать предложение join на основе структуры ваших таблиц и данных, которые вы хотите выбрать, чтобы обновить его, 'CROSS JOIN' объединит каждую строку из первой таблицы с каждой строкой из второй таблицы, так что вы получили декартово произведение строк из двух таблиц, поэтому я думаю, что это не сработает для вас. поэтому попробуйте использовать левое соединение или другие объединения. –