2015-05-04 79 views
0

我有这个存储过程,我想基于变量传递即@Practice_Short_NameSQL Server存储过程动态选择表名

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_'[email protected]_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 '[email protected]+' 

    where Uploaded_Date ='[email protected]_Date+' and 
    Practice_Short_Name ='[email protected]_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'。“

任何人都可以解释我什么我做错了..

+0

看看[sp_executesql](https://msdn.microsoft.com/en-us/library/ms188001.aspx)。运行比使用输入参数构建动态sql更安全 –

+0

奇怪的数据库设计。为什么每个练习的历史表都使用短名称,而不是有一个历史表和一个练习短名称的列,因此您可以使用纯SQL来检索数据? –

+0

如果我把所有的数据放在一张表中,那么我的应用程序运行速度很慢。我在桌上有大约1800,000多条记录。 –

回答

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_'[email protected]_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 '[email protected]+' 

    where Uploaded_Date ='[email protected]_Date+' and 
    Practice_Short_Name ='[email protected]_Short_Name+' 
    order by acer_status asc, Service_Date_From desc, Patient_First_Name asc' 

EXEC (@vQuery) 
end 
GO 
1

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

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

+0

谢谢你的建议。但是,如果我将所有数据放在一张表中,我的应用程序运行速度非常慢。在一张表中,数据大约有1800,000多行。所以我在不同的表格中分隔数据。如果你可以建议我一些其他的方法,这将是非常可观的。 –

+0

根据您的特定条件,您可能可以使用 [分区](https://msdn.microsoft.com/en-us/library/ms190787(v = sql.100).aspx)或者也许只是一些简单的[过滤的索引](https://msdn.microsoft.com/en-us/library/cc280372.aspx),无法确切知道数据和需求的确切性质,无法精确确定答案。 –

0

2件事情需要纠正:导致你这个问题的动态查询变量的长度。使用参数化的动态查询来防止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 
+0

感谢您的回复,因为你建议我增加了变量的大小。但仍然无法正常工作。但如果我从我的查询中删除条件,那么它会正常工作。你可以指导我在哪里条件我做错了什么。 –