Я восстанавливаюсь с ошибки в системе, которую я создал, где я не принял во внимание, что IE генерирует новые строки стиля Windows (\r\n), и другие браузеры генерируют новые строки стиля Unix (\n) при регистрации HTML-форм с текстовыми областями. Теперь я должен преобразовать все новые строки стиля Windows (\r\n) в новые строки стиля Unix (\n) всюду по varchar и nvarchar полям в моей базе данных SQL-Server.
Существует ли способ выполнить итерации через все таблицы/строки в T-SQL и экземплярах замены '\r\n' с '\n' для varchar и nvarchar полей?
Править: Я думаю, что часть замены была бы чем-то как
REPLACE(@fieldContents, CHAR(13)+CHAR(10), CHAR(10))
Твердая часть делает это через весь varchar и nvarchar поля.
Что-то вроде этого? Затем вы можете динамически выполнить эти строки или просто вырезать / вставить результаты и выполнить их в окне запроса.
select 'update ' + sc.name + '.' + t.name + ' set ' + c.name + ' = replace(' + c.name + ', CHAR(13)+CHAR(10), CHAR(10))'
from sys.columns c
inner join sys.systypes st
on c.system_type_id = st.xtype
and CHARINDEX('varchar', st.name) <> 0
inner join sys.tables t
on c.object_id = t.object_id
inner join sys.schemas sc
on t.schema_id = sc.schema_id
Можно выполнить итерацию по системным представлениям в INFORMATION_SCHEMA и запустить для этого динамический SQL. Соответствующим представлением должно быть INFORMATION_SCHEMA.COLUMNS.
Лучший подход, вероятно, заключается в том, чтобы ваш пользовательский интерфейс справился с этим, когда ему нужно отобразить значения. Есть ли у вас метод предотвращения попадания подобных значений в БД в будущем?
Вот пример кода, который должен помочь вам начать:
DECLARE
@table_schema SYSNAME,
@table_name SYSNAME,
@column_name SYSNAME,
@cmd VARCHAR(MAX)
DECLARE cur_string_columns AS
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
DATA_TYPE IN ('VARCHAR', 'CHAR') AND -- NVARCHAR and NCHAR?
CHARACTER_MAXIMUM_LENGTH > 1
OPEN cur_string_columns
FETCH NEXT FROM cur_string_columns INTO @table_schema, @table_name, @column_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT @cmd = 'UPDATE
' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + '
SET ' + QUOTENAME(@column_name) + ' = REPLACE(' + QUOTENAME(@column_name) + ', CHAR(13) + CHAR(10), CHAR(10))'
EXEC(@cmd)
FETCH NEXT FROM cur_string_columns INTO @table_schema, @table_name, @column_name
END
CLOSE cur_string_columns
DEALLOCATE cur_string_columns
Если у вас большие таблицы, это может занять много времени. Кроме того, оптимально было бы обновлять каждую таблицу только один раз, в то время как в этом случае она будет обновляться один раз для каждого столбца строк в таблице. Если бы я делал это на большой базе данных, то я бы изменил сценарий с учетом этого - упорядочил бы курсор по схеме таблицы и имени таблицы, добавил бы к SET часть строки для каждого столбца в таблице, только EXEC(@cmd), когда таблица меняется, а затем сбросил бы строку SET.