Я нашел рабочее решение этой проблемы. MSDN показал мне: http://msdn.microsoft.com/en-US/library/ms175170.aspx. Там написано:
[...] строка исполняется как отдельный пакет.
Это дало мне знать, что если я хочу выполнить динамический оператор с табличной переменной в виде строки, это то же самое, что я бы выполнил запрос без команды EXECUTE
, например:
SELECT TOP(@row_limit) *
FROM @real_table_name
WHERE ...
ORDER BY id ASC;
И это, вероятно, не сработает для имени таблицы.
Итак, если я напишу вместо:
DECLARE @sql_statement nvarchar(MAX) = 'SELECT TOP(@limit) *
FROM ' + @real_table_name + '
ORDER BY id ASC';
-- declaration of parameters for above sql
DECLARE @sql_param_def nvarchar(MAX) = '@limit int';
EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit;
Тогда это будет работать. Это потому, что я определяю @sql_statement просто как сцепленную строку, которая просто преобразует динамическое имя таблицы во время выполнения в строку с именем реально существующей таблицы. Параметр @limit остается без изменений и остается параметром.
Если мы затем выполним пакет, мы должны только передать значение для параметра @limit, и это работает!
Для параметра геометрии он работает аналогично:
DECLARE @bb geometry = geometry::STGeomFromText(@bounding_box, 4326);
SET @sql_statement = 'SELECT TOP(@limit) *
FROM ' + @real_table_name + '
WHERE wkt.STWithin(@geobb) = 1
ORDER BY id ASC';
-- NOTE: This ' = 1' must be set to avoid my above described error (STWithin doesn't return a BOOLEAN!!)
-- declaration of parameters for above sql
SET @sql_param_def = '@limit int, @geobb geometry';
EXECUTE sp_executesql @sql_statement, @sql_param_def, @limit = @row_limit, @geobb = @bb;
Надеюсь, это было ясно; -)