Sql Server存储过程动态选择表名

时间:2015-05-04 11:23:25

标签: sql sql-server-2008 stored-procedures

我有这个存储过程,我想根据传递的变量动态选择表名,即@Practice_Short_Name

 Create procedure [dbo].[GetCompleteCPTDetails]
    @Practice_Short_Name varchar(50) is Null,
    @Uploaded_Date varchar(30) is Null
 as
 begin
 DECLARE @CPTtablename varchar(100)
 DECLARE @vQuery NVARCHAR(100)

 --Dynamically select Table name based on @practice_short_name
 set @CPTtablename ='ACER_CLAIMS_MASTER_DETAIL_Hist_'+@Practice_Short_Name+''

   SET @vQuery = 'select Practice_Short_Name,Service_Date_From,Carrier_Name,
   Location_Description,Patient_Number,Patient_First_Name,
   Patient_Last_Name,Voucher_Number,Procedure_Code,Service_Fees,
   Service_Payments,Service_Adjustments,Acer_Status,Acer_Allowed_Amount    

   from '+@CPTtablename+'

   where  Uploaded_Date ='+@Uploaded_Date+' and
   Practice_Short_Name ='+@Practice_Short_Name+'
   order by acer_status asc, Service_Date_From desc, Patient_First_Name asc'

EXEC @vQuery
end
GO

但是在运行此proc时会抛出类似

的错误

"找不到存储过程'选择Practice_Short_Name,Service_Date_From,Carrier_Name,        Location_Description,Patient_Numb'"

任何人都可以解释我的错误。

3 个答案:

答案 0 :(得分:2)

这样你就可以调用一个程序

EXEC @vQuery

但这样你运行动态sql

EXEC (@vQuery)

所以你的SP应该如下所示

 Create procedure [dbo].[GetCompleteCPTDetails]
    @Practice_Short_Name varchar(50) is Null,
    @Uploaded_Date varchar(30) is Null
 as
 begin
 DECLARE @CPTtablename varchar(100)
 DECLARE @vQuery NVARCHAR(100)

 --Dynamically select Table name based on @practice_short_name
 set @CPTtablename ='ACER_CLAIMS_MASTER_DETAIL_Hist_'+@Practice_Short_Name+''

   SET @vQuery = 'select Practice_Short_Name,Service_Date_From,Carrier_Name,
   Location_Description,Patient_Number,Patient_First_Name,
   Patient_Last_Name,Voucher_Number,Procedure_Code,Service_Fees,
   Service_Payments,Service_Adjustments,Acer_Status,Acer_Allowed_Amount    

   from '+@CPTtablename+'

   where  Uploaded_Date ='+@Uploaded_Date+' and
   Practice_Short_Name ='+@Practice_Short_Name+'
   order by acer_status asc, Service_Date_From desc, Patient_First_Name asc'

EXEC (@vQuery)
end
GO

答案 1 :(得分:1)

用于存储查询的变量太短,无法存储整个查询文本 这意味着截断查询以修复@vQuery变量的100个字符限制。 使用nvarchar(max)代替nvarchar(100)

此外,使用动态SQL通常会带来安全隐患,为SQL Injection attacks留下空缺。您可能想要重新考虑您的设计并将所有数据保存在同一个表中,而不是在数据库中保留具有相同结构的不同表。

答案 2 :(得分:0)

需要纠正的两件事:动态查询变量的长度导致了这个问题。使用参数化动态查询来防止sql注入。

DECLARE @CPTtablename varchar(100)
DECLARE @vQuery NVARCHAR(2000) -- increased length, you can also use nvarchar(max)
--Dynamically select Table name based on @practice_short_name
SET @CPTtablename ='ACER_CLAIMS_MASTER_DETAIL_Hist_' + @Practice_Short_Name + ''
SET @vQuery = 'select Practice_Short_Name,Service_Date_From,Carrier_Name,
   Location_Description,Patient_Number,Patient_First_Name,
   Patient_Last_Name,Voucher_Number,Procedure_Code,Service_Fees,
   Service_Payments,Service_Adjustments,Acer_Status,Acer_Allowed_Amount    

   from ' + @CPTtablename + '

   where  Uploaded_Date = @Uploaded_Date and
   Practice_Short_Name = @Practice_Short_Name
   order by acer_status asc, Service_Date_From desc, Patient_First_Name asc'

--dynamic query with input params
EXEC sp_executesql
  @vQuery,
  N'@Uploaded_Date varchar(30), @Practice_Short_Name varchar(50)',
  @Uploaded_Date = @Uploaded_Date,
  @Practice_Short_Name = @Practice_Short_Name