Search code examples
sql-servert-sqltable-variable

Must declare the table variable error while creating a TVP function


I have the following function created with a TVP. I am inserting data initially into the TVP and then selecting from it.

CREATE FUNCTION [dbo].employees_data(
  @employeeIds NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
-- WITH SCHEMABINDING
AS
BEGIN

  CREATE TYPE employees_data
  AS TABLE (can_view_all BIT,role_id INT ,employee_id INT);

  DECLARE @EmployeeDataTVP AS employees_data;

  INSERT INTO @EmployeeDataTVP (can_view_all, role_id, employee_id)
  SELECT
      ur.role_id,
      ua.employee_id
      INNER JOIN user_roles ur ON ur.user_account_id = ua.id
      WHERE ua.employee_id IN (SELECT * FROM STRING_SPLIT(@employeeIds, ','));


   RETURN (SELECT
    (
      CASE
      WHEN ed.role_id = 1 THEN (
        SELECT
          cc.id,
          ISNULL(cc.standard_name, cc.localized_name) AS name,
          cc.client_cost_center_id AS cost_center_id
        FROM s eccs
        LEFT JOIN centers cc on eccs.center_id = cc.id
        WHERE eccs.employee_id = ed.employee_id
        FOR JSON PATH
      )
      ELSE NULL
    END
    ) AS managed_places,
    ed.employee_id
  FROM @EmployeeDataTVP ed
   )
END

But i get the Must declare the table variable \"@EmployeeDataTVP\". error when i execute the function. I cannot figure out what i am doing wrong.


Solution

  • You do not need to create type but table variable instead:

    CREATE FUNCTION [dbo].employees_data(
      @employeeIds NVARCHAR(MAX)
    )
    RETURNS NVARCHAR(MAX)
    -- WITH SCHEMABINDING
    AS
    BEGIN
    
      DECLARE @EmployeeDataTVP TABLE (can_view_all BIT,role_id INT ,employee_id INT);
    
    
      INSERT INTO @EmployeeDataTVP (can_view_all, role_id, employee_id)
      SELECT
          ur.role_id,
          ua.employee_id
          INNER JOIN user_roles ur ON ur.user_account_id = ua.id
          WHERE ua.employee_id IN (SELECT * FROM STRING_SPLIT(@employeeIds, ','));
    
    
       RETURN (SELECT
        (
          CASE
          WHEN ed.role_id = 1 THEN (
            SELECT
              cc.id,
              ISNULL(cc.standard_name, cc.localized_name) AS name,
              cc.client_cost_center_id AS cost_center_id
            FROM s eccs
            LEFT JOIN centers cc on eccs.center_id = cc.id
            WHERE eccs.employee_id = ed.employee_id
            FOR JSON PATH
          )
          ELSE NULL
        END
        ) AS managed_places,
        ed.employee_id
      FROM @EmployeeDataTVP ed
       )
    END