Как преобразовать переводы строки (заменить \ r \ n на \ n) во всех полях varchar и nvarchar в базе данных - PullRequest
6 голосов
/ 24 июня 2010

Я восстанавливаюсь после ошибки в системе, которую я создал, когда я не учел, что 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.

Ответы [ 2 ]

9 голосов
/ 24 июня 2010

Как то так? Затем вы можете динамически выполнить эти строки или просто вырезать / вставить результаты и выполнить их в окне запроса.

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
1 голос
/ 24 июня 2010

Вы можете перебирать системные представления в 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.

...