Повинен оголосити скалярну змінну


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" The param @ RowFrom / @ RowTo is int, as the Declared ..
bill

4
Так, зрозумів. Ви створюєте рядок SQL і перебуваєте на двох рівнях області. На верхньому рівні ви будуєте рядок - все це об’єднання повинно мати значення рядків, незалежно від того, "5" це, "foo" чи "zuluxxy". Додам приклад для ілюстрації.
Аарон Бертран,


6

Просто FYI, я знаю, що це стара публікація, але залежно від налаштувань ЗБІРКИ бази даних ви можете отримати цю помилку в такому твердженні,

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. Студія і буде працювати. Однак у результаті цих змінних у Visual Studio (C #) з’явиться повідомлення "Обов’язково оголосити скалярну змінну" @MyVariable через різницю між чутливістю до регістру.


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 працювати, ось в чому моя помилка:

Я експортував вміст своєї бази даних за допомогою команди 'Generate Script' у Microsofts '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.