Как вставить разрыв строки в строку SQL Server VARCHAR / NVARCHAR

562

Я не видел подобных вопросов, задаваемых по этой теме, и мне пришлось исследовать это на предмет того, над чем я сейчас работаю. Думал, что выложу ответ на него, если у кого-то будет такой же вопрос.

Марк Струзинский
источник
8
Чтобы проверить вывод, если при использовании SSMS убедитесь, что установлен флажок «Сохранить CR / LF при копировании или сохранении», иначе все вставленные результаты потеряют перевод строки. Вы найдете это в настройках, результатах запросов, SQL Server, результаты в сетке.
Стефанос Зилеллис
1
@StefanosZilellis и обязательно откройте новое окно запроса, чтобы изменения вступили в силу.
Дон Чидл

Ответы:

597

char(13)есть CR. Для переносов строк в стиле DOS / Windows CRLFвы хотите char(13)+char(10), например:

'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'
Сёрен Куклау
источник
28
char (13) + char (10) не работает для меня в Windows. Я просто использовал char (10)
nima
6
@Nima: некоторые приложения будут использовать одно или другое или оба для отображения новой строки, однако многие приложения, для которых вы можете вывести этот текст, будут требовать, чтобы оба отображались последовательно для обозначения новой строки. Я считаю безопасным использовать оба. Здесь вы можете указать, для какого из ваших приложений оно не работает. Я предпочитаю шестнадцатеричные значения CHAR (0x0D) + CHAR (0x0A), но каждому свое.
MikeTeeVee
2
Я успешно использовал этот метод, но столкнулся с проблемой: когда у вас больше 480 +, SQL Server начнет жаловаться, что ваш запрос слишком глубоко вложен. Вместо этого я решил использовать ответ Роба Купера, но с гораздо более длинным и неясным символом.
Маркус Даунинг
5
Предоставление \ r \ n будет означать подтверждение того, что регулярные выражения существуют и что есть пользователи, способные понимать и использовать их.
wwmbes
10
@HBlackorby \ r и \ n предшествуют Java-чему-либо на десятилетия благодаря их использованию в C; и являются стандартными в Python, PHP, Ruby, C ++, C # и т. д.
Uueerdo
286

Я нашел ответ здесь: http://blog.sqlauthority.com/2007/08/22/sql-server-t-sql-script-to-insert-carriage-return-and-new-line-feed-in- код/

Вы просто конкатенируете строку и вставляете туда, CHAR(13)где хотите разрыв строки.

Пример:

DECLARE @text NVARCHAR(100)
SET @text = 'This is line 1.' + CHAR(13) + 'This is line 2.'
SELECT @text

Это распечатывает следующее:

Это строка 1.
Это строка 2.

Марк Струзинский
источник
11
ОБНОВЛЕНИЕ: забудь об этом. Вставляет просто отлично. Это студия управления, которая заменяет вкладки и символы новой строки пробелами для видимости
Даниэль Долз
12
Кажется, вам нужно использовать PRINT @text, а не SELECT, чтобы получить этот результат.
QMaster
3
Кстати: вы также можете использовать, NCHAR(0x1234)чтобы получить символ Unicode. Не требуется для вставки разрывов строк, но может пригодиться, если нужно вставить / найти символы Юникода.
Пол Грок,
3
В SQL Server 2016 я вижу только вывод двух строк, если я использую printвместо них select, например:DECLARE @text NVARCHAR(100); SET @text = 'This is line 1.' + CHAR(13) + 'This is line 2.'; print @text;
devinbost
7
Чтобы проверить вывод, если при использовании SSMS убедитесь, что установлен флажок «Сохранить CR / LF при копировании или сохранении», иначе все вставленные результаты потеряют перевод строки. Вы найдете это в настройках, результатах запросов, SQL Server, результаты в сетке.
Дон Чидл
81

Другой способ сделать это так:

INSERT CRLF SELECT 'fox 
jumped'

То есть простая вставка разрыва строки в запросе во время записи добавит аналогичный разрыв в базу данных. Это работает в SQL Server Management Studio и Query Analyzer. Я считаю, что это также будет работать в C #, если вы используете знак @ в строках.

string str = @"INSERT CRLF SELECT 'fox 
    jumped'"
Фрэнк V
источник
14
Другими словами, синтаксис языка SQL просто допускает необработанные переводы строк в строковых литералах. Это работает таким образом во всех движках, которые я пробовал (SQL Server, Oracle, MySQL, PostgreSQL и SQLite).
Альваро Гонсалес,
иногда это случайно перестает работать, если вы используете его в хранимых процедурах
DaFi4
25

Запустите это в SSMS, оно показывает, как разрывы строк в самом SQL становятся частью строковых значений, которые охватывают строки:

PRINT 'Line 1
Line 2
Line 3'
PRINT ''

PRINT 'How long is a blank line feed?'
PRINT LEN('
')
PRINT ''

PRINT 'What are the ASCII values?'
PRINT ASCII(SUBSTRING('
',1,1))
PRINT ASCII(SUBSTRING('
',2,1))

Результат:
Строка 1
Строка 2
Строка 3

Сколько времени занимает пустая строка?
2

Каковы значения ASCII?
13
10

Или, если вы предпочитаете указывать свою строку в одной строке (почти!), Вы можете использовать REPLACE()это (необязательно использовать CHAR(13)+CHAR(10)в качестве замены):

PRINT REPLACE('Line 1`Line 2`Line 3','`','
')
AjV Jsy
источник
16

После Google ...

Взяв код с сайта:

CREATE TABLE CRLF
    (
        col1 VARCHAR(1000)
    )

INSERT CRLF SELECT 'The quick brown@'
INSERT CRLF SELECT 'fox @jumped'
INSERT CRLF SELECT '@over the '
INSERT CRLF SELECT 'log@'

SELECT col1 FROM CRLF

Returns:

col1
-----------------
The quick brown@
fox @jumped
@over the
log@

(4 row(s) affected)


UPDATE CRLF
SET col1 = REPLACE(col1, '@', CHAR(13))

Похоже, это можно сделать, заменив заполнитель на CHAR (13)

Хороший вопрос, никогда не делал это сам :)

Роб Купер
источник
4
Но если в тексте есть адрес электронной почты? «jon@bob.com» становится «jon bob.com» (с новой строкой в ​​электронном платье)
intrepidis
4
Затем @ChrisNash использует другой заполнитель (например, «|», «~» или несколько символов «! #!»). Смотрите этот ответ ниже: stackoverflow.com/a/31179/179311 .
bradlis7
1
«CONCAT (CHAR (13), CHAR (10))» («\ r \ n») будет лучше для среды Windows, что, как я полагаю, имеет место (SQL Server) cs.toronto.edu/~krueger/csc209h/ tut / line-endings.html
d.popov
12

Я попал сюда, потому что был обеспокоен тем, что cr-lfs, которые я указал в строках C #, не показывались в ответах на запросы SQl Server Management Studio.

Оказывается, они есть, но не отображаются.

Чтобы «увидеть» cr-lfs, используйте оператор print, например:

declare @tmp varchar(500)    
select @tmp = msgbody from emailssentlog where id=6769;
print @tmp
Брюс Аллен
источник
4

Вот функция C #, которая добавляет текстовую строку к существующему текстовому объекту, разделяется CRLF и возвращает выражение T-SQL, подходящее для операций INSERTили UPDATE. В нем есть часть нашей собственной обработки ошибок, но как только вы ее удалите, это может быть полезно - я надеюсь на это.

/// <summary>
/// Generate a SQL string value expression suitable for INSERT/UPDATE operations that prepends
/// the specified line to an existing block of text, assumed to have \r\n delimiters, and
/// truncate at a maximum length.
/// </summary>
/// <param name="sNewLine">Single text line to be prepended to existing text</param>
/// <param name="sOrigLines">Current text value; assumed to be CRLF-delimited</param>
/// <param name="iMaxLen">Integer field length</param>
/// <returns>String: SQL string expression suitable for INSERT/UPDATE operations.  Empty on error.</returns>
private string PrependCommentLine(string sNewLine, String sOrigLines, int iMaxLen)
{
    String fn = MethodBase.GetCurrentMethod().Name;

    try
    {
        String [] line_array = sOrigLines.Split("\r\n".ToCharArray());
        List<string> orig_lines = new List<string>();
        foreach(String orig_line in line_array) 
        { 
            if (!String.IsNullOrEmpty(orig_line))  
            {  
                orig_lines.Add(orig_line);    
            }
        } // end foreach(original line)

        String final_comments = "'" + sNewLine + "' + CHAR(13) + CHAR(10) ";
        int cum_length = sNewLine.Length + 2;
        foreach(String orig_line in orig_lines)
        {
            String curline = orig_line;
            if (cum_length >= iMaxLen) break;                // stop appending if we're already over
            if ((cum_length+orig_line.Length+2)>=iMaxLen)    // If this one will push us over, truncate and warn:
            {
                Util.HandleAppErr(this, fn, "Truncating comments: " + orig_line);
                curline = orig_line.Substring(0, iMaxLen - (cum_length + 3));
            }
            final_comments += " + '" + curline + "' + CHAR(13) + CHAR(10) \r\n";
            cum_length += orig_line.Length + 2;
        } // end foreach(second pass on original lines)

        return(final_comments);


    } // end main try()
    catch(Exception exc)
    {
        Util.HandleExc(this,fn,exc);
        return("");
    }
}
Карл Ниднер
источник
4

я бы сказал

concat('This is line 1.', 0xd0a, 'This is line 2.')

или

concat(N'This is line 1.', 0xd000a, N'This is line 2.')
Кен Кин
источник
3

Это всегда круто, потому что когда вы получаете экспортированные списки, скажем, из Oracle, то вы получаете записи, занимающие несколько строк, которые, в свою очередь, могут быть интересны, скажем, для файлов cvs, так что будьте осторожны.

В любом случае, ответ Роба хороший, но я бы посоветовал использовать что-то еще, кроме @, попробуйте еще что-нибудь, например, §§ @@ §§ или что-то в этом роде, чтобы у него была какая-то уникальность. (Но все же помните длину поля varchar/, которое nvarcharвы вставляете в ..)

neslekkiM
источник
3

Все эти параметры работают в зависимости от вашей ситуации, но вы можете не увидеть ни одного из них, если используете SSMS (как упоминалось в некоторых комментариях, SSMS скрывает CR / LF)

Так что вместо того, чтобы ехать за поворотом, проверьте этот параметр в

Tools | Options

который заменит

Trubs
источник