Должен объявить скалярную переменную

@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 и генерирует ошибку.

Ответ 1

Вы не можете объединить 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 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 sp_executesql @sql,
  N'@RowFrom INT, @RowTo INT',
  @RowFrom, @RowTo;

Ответ 2

Просто FYI, я знаю, что это старый пост, но в зависимости от настроек 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;

Ответ 4

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

Смотрите этот вопрос и этот обходной путь.

Ответ 5

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

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

Ответ 6

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

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'

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

Must declare the scalar variable "@year"

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