Как запустить SQL-запрос более 8000 символов из переменной?

Я могу использовать следующий код для крошечных маленьких запросов:

DECLARE @sql VARCHAR(8000)
SET @sql = 'SELECT * FROM myTable'
Exec @sql

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

Моя проблема заключается в том, что мой запрос (это всего лишь один запрос), который я хочу передать в переменную @sql, использует более 25 табличных объединений, некоторые из них по временным табличным переменным, включают в себя сложные операции и, следовательно, его длина превышает 8000 символов.,

Я хотел использовать тип данных TEXT для хранения этого запроса, но MSDN показывает предупреждающее сообщение о том, что Microsoft планирует удалить типы данных Text, NText и Image из своих следующих версий. Я хочу, чтобы мой код работал в будущем.

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

Пожалуйста, скажите мне метод, чтобы сохранить большой запрос в переменной и выполнить его несколько раз в процедуре.

Ответы

Ответ 1

Если вы находитесь на SQL Server 2008 или новее, вы можете использовать VARCHAR (MAX)

DECLARE @sql VARCHAR(MAX)

Ответ 2

Проблема заключается в неявном преобразовании.

Если у вас есть значения Unicode/nChar/nVarChar, которые вы объединяете, SQL Server будет неявно преобразовывать вашу строку в VarChar (8000), и, к сожалению, это слишком глупо, чтобы понять, что она усечет вашу строку или даже даст вам предупреждение о том, что данные были усечены в этом отношении!

Когда конкатенирование длинных строк (или строк, которые, по вашему мнению, могут быть длинными), всегда предварительно конкатенируйте строковое построение с помощью CAST ( "как" nVarChar (MAX)):

SET @Query = CAST('' as nVarChar(MAX))--Force implicit conversion to nVarChar(MAX)
           + 'SELECT...'-- some of the query gets set here
           + '...'-- more query gets added on, etc.

Какая боль и страшно думать, что именно так работает SQL Server. : (

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

Для тех, кто набрал максимум 4000 символов, вероятно, потому, что у вас был Unicode, поэтому он был неявно преобразован в nVarChar (4000).

Объяснение:
То, что происходит за кулисами, заключается в том, что даже если переменная, которую вы назначаете для использования (MAX), SQL Server будет оценивать правую часть значения, которое вы назначаете первым, и по умолчанию - nVarChar (4000) или VarChar (8000) (в зависимости от на то, что вы конкатенируете). После того, как вы закончите вычислять значение (и после усечения его для вас), он затем преобразует его в (MAX) при назначении его переменной, но к тому времени уже слишком поздно.

Ответ 3

DECLARE @sql VARCHAR(max)
SET @sql = 'SELECT * FROM myTable'
Exec @sql

Примечание:

Print(@sql)

отображаются только первые 8000 символов!

Ответ 4

Проблема заключается в том, что по умолчанию ваша строка имеет ограничение по 8000 символов. Чтобы предотвратить это, вы должны преобразовать его в (N) VARCHAR (MAX)

DECLARE @sql VARCHAR(8000)
        SET @sql = CAST('SELECT * FROM myTable' AS VARCHAR(MAX))
--Check length of variable
 PRINT 'Length is: '+CAST(LEN(@sql) AS VARCHAR)+ 'symbols'
        Exec @sql

Ответ 5

использовать

EXEC
(
  '
   --your sql script here
  '
)

Ответ 6

Вы должны прочитать ответ на этот пост, который очень хорошо объясняет ситуацию: Ограничения SQL NVARCHAR и VARCHAR

  • Если длина x вашей строки меньше 4000 символов, строка будет преобразована в nvarchar(x)
  • Если длина y находится между 4000 и 8000, varchar(y)
  • Если длина превышает 8000 символов, nvarchar(max), которая может хранить до 2 ГБ.

Проблема в том, что nvarchar(max) + varchar(y) = nvarchar(max) + nvarchar(4000); SQL преобразует ваш varchar(y) в nvarchar(y) или nvarchar(4000), если y больше 4000 и меньше 8000, усекая вашу строку!

Ответ 7

Хорошо, что я использовал это раньше (в SQL 2005), и могу сказать, что у вас есть два варианта:

1 - Используйте хранимую процедуру sys.sp_sqlexec, которая может принимать параметр текста типа (IMO - это путь). Не обращайте внимания на предупреждение. В SQL 2008 ntext по-прежнему поддерживается, и если вы выполните там varchar (max), он будет работать. Так что в принципе, если у вас есть 2008, как текстовое решение, так и varchar (max) будут работать, поэтому у вас будет время изменить его = -). В 2012 году, однако, будет работать только varchar (max), поэтому вам придется изменить его перед обновлением.

2- (Это то, что я сделал сначала). Проверьте это сообщение: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=52274 и сделайте то, что говорит пользователь "Кристен". Работала для меня как шарм. Не забудьте предварительно установить их на пустую строку. Если вы поняли мое сообщение, вы уже знаете, что в SQL 2008 или новее глупо это делать.

Ответ 8

Нет решения для этого, как вы это делаете. MsSql по состоянию на 2012 год поддерживает Ntext, например, который позволяет выходить за пределы 8000 символов в переменной. Способ решения этой проблемы состоит в том, чтобы сделать несколько переменных или несколько строк в таблице, через которую можно выполнить итерацию.

В лучшем случае с версией MsSql максимальный размер переменной составляет 8000 символов в последней версии с момента ее ввода. Поэтому, если вы имеете дело с строкой, скажем, 80 000 символов. Вы можете анализировать данные на десять переменных из 8000 символов каждый (8000 x 10 = 80 000), или вы можете нарезать переменную на куски и поместить ее в таблицу, скажем, LongTable (Bigstring Varchar (8000)), вставьте в нее 10 строк и используйте Значение идентификатора, чтобы вы могли получить данные в том же порядке.

Метод, который вы пытаетесь, не будет работать с MsSql в настоящее время.

Другой неясный вариант, который будет работать, но не рекомендуется, - это сохранить переменную в текстовом файле, используя команды командной оболочки для чтения/записи файла. Тогда у вас есть пространство для вас, превышающее 8000 символов. Это медленнее и менее безопасно, чем другие методы, описанные выше.

Ответ 9

ALTER PROCEDURE [dbo].[spGetEmails]
AS
BEGIN
    SET NOCOUNT ON;
    -- Insert statements for procedure here

    declare @p varbinary(max)
set @p = 0x
declare @local table (col text)

SELECT   @p = @p + 0x3B + CONVERT(varbinary(100), Email)
 FROM tbCarsList
 where email <> ''
 group by email
 order by email

 set @p = substring(@p, 2, 10000000)

 insert @local values(cast(@p as varchar(max)))
 select   col from @local


END

Ответ 10

У меня возникла та же проблема с усеченными строками. Я узнал, что вы можете выполнить инструкцию sp_executesql несколько раз.

Так как мой блок кода превышал предел 4k/Max, я разбил его на маленькие кусочки:

set @statement = '                                                                                      
update pd                               
set pd.mismatchtype = 4                             
  FROM [E].[dbo].[' + @monthName + '_P_Data] pd                             
  WHERE pd.mismatchtype is null '                                                                               
exec sp_executesql @statement                               


set @statement = 'Select * from xxxxxxx'
exec sp_executesql @statement

set @statement = 'Select * from yyyyyyy '
exec sp_executesql @statement

end

Таким образом, каждый набор @Statement может иметь varchar (max), если каждый чанк находится в пределах предела размера (я вырезал реальный код в моем примере, из соображений экономии места)

Ответ 11

Я была такая же проблема. У меня есть SQL, который был более 21 000 символов. По какой-то причине

Declare @SQL VARCHAR(MAX)

EXEC(@SQL) 

придумал бы несколько вопросов

Я должен был, наконец, разделить его на несколько переменных, и тогда это сработало.

    Declare @SQL1 VARCHAR(MAX) = 'First Part'
    Declare @SQL2 VARCHAR(MAX) = 'Second  Part'
    Declare @SQL3 VARCHAR(MAX) = 'Third Part'
    Declare @SQL4 VARCHAR(MAX) = 'Fourth Part'

    Set @SQL= @SQL1 + @SQL2 + @SQL3 + @SQL4

    EXEC(@SQL)

Ответ 12

Перед печатью преобразуйте в группу и измените тип данных.

PRINT CAST(@sql AS NTEXT)

Теперь попробуй это.

Ответ 13

Если вы пытаетесь сделать это в Management Studio, может помочь следующий сценарий.

DECLARE @Len INT = 5
DECLARE @Str VARCHAR(MAX) = '1111122222333334444455555'
DECLARE @TmpStr VARCHAR(MAX)
DECLARE @Return TABLE (RetStr VARCHAR(MAX))

WHILE(LEN(@Str) > 0)
BEGIN
    SET @TmpStr = LEFT(@Str, @Len)
    IF(LEN(@Str) > @Len)
        SET @Str = RIGHT(@Str, LEN(@Str) - @Len)
    ELSE
        SET @Str = ''
    INSERT INTO @Return SELECT @Str
END

SELECT * FROM @Return

Там @Len должно быть 8000, поскольку это максимальная длина, которую показывает Management Studio. @Str - это текст длиной более 8000 символов.