Необходимо объявить скалярную переменную


81

@RowFrom int

@RowTo int

являются глобальными входными параметрами для хранимой процедуры, и поскольку я компилирую SQL-запрос внутри хранимой процедуры с помощью T-SQL, а затем использую Exec(@sqlstatement)в конце хранимой процедуры для отображения результата, это дает мне эту ошибку, когда я пытаюсь использовать @RowFromили @RowToвнутри @sqlstatementпеременной , которая выполняется .. она отлично работает иначе .. пожалуйста помощь.

"Must declare the scalar variable "@RowFrom"."

Кроме того, я попытался включить в @sqlstatementпеременную следующее:

'Declare @Rt int'
'SET @Rt = ' + @RowTo

но по- @RowToпрежнему не передает свое значение @Rt и генерирует ошибку.


5
Я не буду добавлять ответ, потому что он не относится к этому вопросу конкретно, но в качестве первого результата в Google для этой ошибки стоит отметить, что использование GOвызывает новую ветвь, в которой объявленные переменные не видны после оператора.
IronSean

Ответы:


75

Вы не можете объединить int со строкой. Вместо:

SET @sql = N'DECLARE @Rt int; SET @Rt = ' + @RowTo;

Тебе нужно:

SET @sql = N'DECLARE @Rt int; SET @Rt = ' + CONVERT(VARCHAR(12), @RowTo);

Чтобы проиллюстрировать, что здесь происходит. Допустим, @RowTo = 5.

DECLARE @RowTo int;
SET @RowTo = 5;

DECLARE @sql nvarchar(max);
SET @sql = N'SELECT ' + CONVERT(varchar(12), @RowTo) + ' * 5';
EXEC sys.sp_executesql @sql;

Чтобы превратить это в строку (даже если в конечном итоге это будет число), мне нужно преобразовать его. Но, как видите, число по-прежнему рассматривается как число при выполнении. Ответ 25, не так ли?

В вашем случае вам действительно не нужно повторно объявлять @Rt и т. Д. Внутри строки @sql, вам просто нужно сказать:

SET @sql = @sql + ' WHERE RowNum BETWEEN ' 
    + CONVERT(varchar(12), @RowFrom) + ' AND ' 
    + CONVERT(varchar(12), @RowTo);

Хотя было бы лучше иметь правильную параметризацию, например

SET @sql = @sql + ' WHERE RowNum BETWEEN @RowFrom AND @RowTo;';

EXEC sys.sp_executesql @sql,
  N'@RowFrom int, @RowTo int',
  @RowFrom, @RowTo;

2
Спасибо, а что делает N?
банкнота

3
Он гарантирует, что ваша @sqlпеременная интерпретируется правильно как NVARCHAR- требование при использовании sp_executesql...
Аарон Бертран,

1
Ну, они должны быть Int, потому что они используются как "Where RowNum Between @RowFrom and @RowTo" Параметр @ RowFrom / @ RowTo имеет значение int, а также Declared ..
законопроект

4
Да поняла. Вы строите строку SQL и находитесь на двух уровнях области видимости. На верхнем уровне вы создаете строку - вся эта конкатенация должна быть со строковыми значениями, независимо от того, являются ли они «5», «foo» или «zuluxxy». Я добавлю пример для иллюстрации.
Аарон Бертран,


6

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

SET @sql = @Sql + ' WHERE RowNum BETWEEN @RowFrom AND @RowTo;';

если, например, вы напечатали букву S в

SET @sql = @***S***ql 

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

Также обратите внимание, что ошибка не будет отображать заглавную букву S в сообщении, я не знаю почему, но я думаю, что это потому, что

Set @sql =

находится слева от знака равенства.


3

Просто добавляю то, что исправило это для меня, где, согласно этому блогу MSDN, подозревается неправильное написание ...

При разделении строк SQL на несколько строк убедитесь, что вы отделяете строку SQL от параметров запятой (и не пытаетесь их объединить!) И не пропускаете пробелов в конце каждой строки разделения. Не ракетостроение, но надеюсь, что избавлю кого-то от головной боли.

Например:

db.TableName.SqlQuery(
    "SELECT Id, Timestamp, User " +
    "FROM dbo.TableName " +
    "WHERE Timestamp >= @from " +
    "AND Timestamp <= @till;" + [USE COMMA NOT CONCATENATE!]
    new SqlParameter("from", from),
    new SqlParameter("till", till)),
    .ToListAsync()
    .Result;

0

Чувствительность к регистру также вызовет эту проблему.

@MyVariable и @myvariable - это одни и те же переменные в SQL Server Man. Студия так и будет работать. Однако использование этих переменных приведет к появлению сообщения «Необходимо объявить скалярную переменную« @MyVariable »в Visual Studio (C #) из-за различий в чувствительности к регистру.


0

Просто ответ для будущего меня (может быть, это поможет и кому-то другому!). Если вы попытаетесь запустить что-то подобное в редакторе запросов:

USE [Dbo]
GO

DECLARE @RC int

EXECUTE @RC = [dbo].[SomeStoredProcedure] 
   2018
  ,0
  ,'arg3'
GO

SELECT month, SUM(weight) AS weight, SUM(amount) AS amount 
FROM SomeTable AS e 
WHERE year = @year AND type = 'M'

И вы получите ошибку:

Необходимо объявить скалярную переменную «@year»

Это потому, что вы пытаетесь запустить кучу кода, который включает как выполнение хранимой процедуры, так и запрос под ней (!). Просто выделите тот, который хотите запустить, или удалите / закомментируйте тот, который вам не интересен.


0

Если кто-то еще сталкивается с этим вопросом, в то время как никакое решение здесь не заставило мой sql файл работать, вот в чем была моя ошибка:

Я экспортировал содержимое своей базы данных с помощью команды «Создать сценарий» в Microsoft Server Management Studio, а затем выполнял некоторые операции, вставляя сгенерированные данные в другой экземпляр.

Из-за сгенерированного экспорта в sql-файле было несколько операторов «GO».

Чего я не знал, так это того, что переменные, объявленные в верхней части файла, недоступны, пока выполняется инструкция GO. Поэтому мне пришлось удалить операторы GO в моем sql-файле, и ошибка «Необходимо объявить скалярную переменную xy» исчезла!


0

Скорее всего, это не ответ на саму проблему, но этот вопрос появляется как первый результат при поиске Sql declare scalar variable поэтому я поделюсь возможным решением этой ошибки.

В моем случае эта ошибка была вызвана использованием ; после оператора SQL. Просто удалите его, и ошибка исчезнет.

Я предполагаю, что причина та же, что и @IronSean, уже опубликованный в комментарии выше:

Стоит отметить, что использование GO (или в данном случае;) вызывает новую ветку, в которой объявленные переменные не видны за оператором.

Например:

DECLARE @id int
SET @id = 78

SELECT * FROM MyTable WHERE Id = @var; <-- remove this character to avoid the error message
SELECT * FROM AnotherTable WHERE MyTableId = @var
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.