Вызов функции табличного значения в хранимой процедуре

#sql #sql-server #tsql #ssms

#sql #sql-сервер #tsql #ssms

Вопрос:

Я создал хранимую процедуру с именем «CallTableValuedFunctionWithSTRINGParameter». Мой план — вызвать функцию с табличным значением из моего кода на C #, но я не нахожу чистым для простого создания нового SqlCommand с SELECT * FROM SearchBookFromId(" bookId ")" помощью … Итак, я создал хранимую процедуру, которая вызывает эту табличную функцию.

Вот код хранимой процедуры. Учтите, что все имеет SET ANSI_NULLS ON и SET QUOTED_IDENTIFIER ON в качестве стандарта:

 CREATE PROCEDURE CallTableValuedFunctionWithSTRINGParameter
    @functionName VARCHAR(255),
    @parameter VARCHAR(255)
AS
BEGIN
    SET NOCOUNT ON;
    RETURN('SELECT * FROM '   @functionName   '('   @parameter   ')')
END
 

тогда я EXECUTE это:

 DECLARE @functionName varchar(255)
DECLARE @parameter varchar(255)

SET @functionName = 'SearchBookFromId'
SET @parameter = '49'

EXECUTE [dbo].[CallTableValuedFunctionWithSTRINGParameter]
   @functionName
  ,@parameter
 

но я получаю эту ошибку:

Ошибка преобразования при преобразовании значения varchar ‘SELECT * ИЗ SearchBookFromId(49)’ в тип данных int

Здесь приведен код функции с табличным значением SearchBookFromId :

 CREATE FUNCTION [dbo].[SearchBookFromId]
(   
    @bookId VARCHAR(255)
)
RETURNS TABLE
AS
RETURN 
(
    SELECT *
    FROM dbo.Books
    WHERE CAST(BookID AS VARCHAR(255)) = @bookId
)
 

BookID INT поэтому я привел его как VARCHAR .

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

 DECLARE @function VARCHAR(255)
DECLARE @parameter VARCHAR(255)

SET @function = 'SearchBookFromId'
SET @parameter = '49'

EXEC('SELECT * FROM '   @function   '('   @parameter   ')')
 

Комментарии:

1. ПРЕДУПРЕЖДЕНИЕ Это широко открыто для инъекционных атак. Если вы «должны» использовать динамический sql, то правильно заключите имена ваших объектов в кавычки, используя QUOTENAME , и параметризуйте операторы (что вы не можете сделать с EXEC(@SQL) синтаксисом, вам нужно использовать sys.sp_executesql ).

2. Однако на самом деле это похоже на проблему XY . Почему вы хотите , чтобы процедура запускала TVF? Почему эта процедура должна быть динамической? TVF и процедуры являются очень сложными типами объектов, и вы эффективно удаляете точку TVF, вызывая его из процедуры. Вы не можете сделать что-то вроде SELECT * FROM dbo.CallTableValuedFunctionWithSTRINGParameter N'dbo', N'SearchBookFromId, 7;

3. И RETURN в sproc всегда есть только одно int значение

4. Причина Conversion failed when converting the varchar value 'SELECT * FROM SearchBookFromId(49)' to data type int ошибки заключается в том, что RETURN ожидается целочисленное выражение.

5. Процитирую известную фразу @Alex95: «Те, кто не может, учат».