Single Proc in Single Proc?

时间:2011-09-13 11:50:30

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

我是SQL Server 2008的新手。我正在使用三个表。我已经为我的结果创建了两个Proc。但是我希望将这两个Proc组合在单个Proc中。 以下是我的过程 -

First Proc -

CREATE PROC [GetPaymentGateway]  
 @CompanyID VARCHAR(3),  
 @CCMSalesChannel VARCHAR(50)  
AS  

declare @mainquery varchar(max)  
set @mainquery='SELECT credit_card_master.card_name, credit_card_master.card_type,'+ @CCMSalesChannel +' FROM credit_card_master 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = credit_card_master.payment_gateway_code  
WHERE [company_id] = '''+@CompanyID+''''  
exec (@mainquery)

Second Proc -

CREATE PROC [GetPaymentGateway2]  
 @CompanyID VARCHAR(3),  
 @NBSalesChannel VARCHAR(50)  
AS  

declare @mainquery varchar(max)  
set @mainquery='SELECT PG_NetBanking_Charges.Online_DC_Charge_Amt, PaymentGateway_master.Payment_Gateway_Name,'+ @NBSalesChannel +' FROM PG_NetBanking_Charges 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = PG_NetBanking_Charges.payment_gateway_code  
WHERE [company_id] = '''+@CompanyID+''''  
exec (@mainquery)

请建议我。是否可以使用哈希表等。

提前致谢。

编辑 - 我希望这两个结果在单个结果中(如在单个表格中)

编辑 - 我的表格中有五列,但我会选择哪一列,它会根据参数在运行时间知道。

2 个答案:

答案 0 :(得分:3)

除非绝对必要,否则你应该避免在存储过程中执行那种SQL,并且你有1000%确定你正确地清理输入。事实上,所有输入参数都是varchar,这些似乎是用于检索支付信息的存储过程,至少可以说是令人不安的。通过在procs中执行这种动态sql,你仍然容易受到SQL注入攻击。

两个过程都可以在一个过程中重写如下:

CREATE PROC [GetPaymentGateway]  
 @CompanyID VARCHAR(3),  
 @NBSalesChannel VARCHAR(50)  =null,
 @CCMSalesChannel VARCHAR(50)  =null
AS  
BEGIN
SELECT [card_name], [card_type],@CCMSalesChannel as CCMSalesChannel FROM credit_card_master 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = credit_card_master.payment_gateway_code  
WHERE [company_id] = @CompanyID

SELECT PG_NetBanking_Charges.Online_DC_Charge_Amt, PaymentGateway_master.Payment_Gateway_Name, @NBSalesChannel as NBSalesChannel  FROM PG_NetBanking_Charges 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = PG_NetBanking_Charges.payment_gateway_code  
WHERE [company_id] = @CompanyID

END

或者你想要这个:

CREATE PROC [GetPaymentGateway]  
 @CompanyID VARCHAR(3),  
 @NBSalesChannel VARCHAR(50)  =null,
 @CCMSalesChannel VARCHAR(50)  =null
AS  
BEGIN
if (@CCMSalesChannel is not null)
begin
SELECT [card_name], [card_type],@CCMSalesChannel as CCMSalesChannel FROM credit_card_master 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = credit_card_master.payment_gateway_code  
WHERE [company_id] = @CompanyID
end

else if (@NBSalesChannel is not null)
begin
SELECT PG_NetBanking_Charges.Online_DC_Charge_Amt, PaymentGateway_master.Payment_Gateway_Name, @NBSalesChannel as NBSalesChannel  FROM PG_NetBanking_Charges 
INNER JOIN PaymentGateway_master
ON PaymentGateway_master.payment_gateway_code = PG_NetBanking_Charges.payment_gateway_code  
WHERE [company_id] = @CompanyID
end

END

更新通常,可以根据“运行时”的参数选择特定列,如下所示:

SELECT PG_NetBanking_Charges.Online_DC_Charge_Amt, PaymentGateway_master.Payment_Gateway_Name,  
 case @NBSalesChannel when 'value1' then ColumnA 
 when 'value2' then ColumnB
 when 'anothervalue' then ColumnC
 when 'yet_another_value' then ColumnD else 
 ColumnE end as SalesChannel  
 FROM PG_NetBanking_Charges 
    INNER JOIN PaymentGateway_master
    ON PaymentGateway_master.payment_gateway_code = PG_NetBanking_Charges.payment_gateway_code  
    WHERE [company_id] = @CompanyID

答案 1 :(得分:1)

无论是谁为存储过程展示了这种模板,都是错误的。在少数情况下,动态查询执行可能很有用,但在您的情况下,只是过度杀伤,性能和安全隐患。程序应该是:

CREATE PROC [GetPaymentGateway]  
  @CompanyID VARCHAR(3)
AS  
BEGIN
  SELECT ccm.card_name, ccm.card_type,
    -- all possible values for the @CCMSalesChannel param here 
    -- (unless there are 50 of them, in which case the db design is wrong)
  FROM credit_card_master ccm
    INNER JOIN PaymentGateway_master pm
    ON pm.payment_gateway_code =ccm.payment_gateway_code  
  WHERE company_id = @CompanyID
END

CREATE PROC [GetPaymentGateway2]
  @CompanyID VARCHAR(3)
AS
BEGIN
  SELECT bc.Online_DC_Charge_Amt, m.Payment_Gateway_Name,
    -- all possible values for the @NBSalesChannel param here 
  FROM PG_NetBanking_Charges bc
    INNER JOIN PaymentGateway_master m
    ON m.payment_gateway_code = bc.payment_gateway_code
  WHERE company_id = @CompanyID
END

也就是说,要将它们连接到单个proc中,您可以传递一个额外的参数,该参数将决定运行哪个查询,并相应地返回结果,如下所示:

CREATE PROC [GetPaymentGateway]  
  @CompanyID VARCHAR(3),
  @Type int
AS  
  if (@Type = 1) 
  BEGIN
    SELECT ccm.card_name, ccm.card_type,
      -- all possible values for the @CCMSalesChannel param here 
    FROM credit_card_master ccm
      INNER JOIN PaymentGateway_master pm
      ON pm.payment_gateway_code =ccm.payment_gateway_code  
    WHERE company_id = @CompanyID
  END
  ELSE IF (@Type = 2)
  BEGIN
    SELECT bc.Online_DC_Charge_Amt, m.Payment_Gateway_Name,
      -- all possible values for the @NBSalesChannel param here 
    FROM PG_NetBanking_Charges bc
      INNER JOIN PaymentGateway_master m
      ON m.payment_gateway_code = bc.payment_gateway_code
    WHERE company_id = @CompanyID
 END

但是,由于看起来返回的记录不太相似,我会坚持两个程序,针对两种不同的情况。


对于参数的所有可能值:

  1. 如果只有少数(可枚举的)选项,我们称之为Column1,Column2和Column3,您可以像这样使用searched case expression

    SELECT 
      case when @NBSalesChannel='Column1' then Column1
           when @NBSalesChannel='Column2' then Column2
           when @NBSalesChannel='Column3' then Column3
           else null
      end as NBSalesChannel
    FROM ...
    
  2. 您可以简单地选择所有可能的列并使用应用程序端代码来获取您想要的内容 - 这里会有一些开销,但查询会更简单

    SELECT Column1, Column2, Column3
    FROM ...
    
  3. 如果你不知道哪些列可用,那么作为最后的手段使用动态sql,但要非常清楚像SQL注入这样的问题(this是一篇很棒的文章,我总是使用它我需要动态SQL的接缝