2016-11-28 62 views
0

我需要將一個列表傳遞給我的SQL Server存儲過程。我已生成的列表中,這是一個逗號分隔的使用數字的列表:我想將一個評估列表傳遞給我的SQL Server存儲過程

<cfquery name="House" datasource="#application.datasource#"> 
    SELECT cGLsubaccount 
    FROM HOUSE 
    WHERE Right(cGLsubaccount,3) IN 
     (
      <cfloop index="i" list="#consulsub#"> 
       <cfoutput>#right(Trim(i) , 3)#,</cfoutput> 
      </cfloop> 
      00000000 
     ) 
</cfquery> 

<cfset GLsubacct = Valuelist(House.cGLsubaccount,",")> 

現在,我將它傳遞到使用cfprocparam與cfsqltype爲varchar(1000)的存儲過程。 (我在google上讀到這是將列表傳遞給存儲過程的方式)。

<cfprocparam type="IN" value="#GLsubacct#" DBVARNAME="@GLsubacct" cfsqltype="cf_sql_varchar"> 

在存儲過程中,我這樣做:

ALTER PROCEDURE [rw].[sp_EFT_NoticeXLS2] (
     @Scope varchar(50) 
     , @AcctPeriod char(6) 
     , @CompanyID nchar(10) 
     , @GLsubacct varchar(1000) = NULL 
) 
AS...... 

,並在存儲過程中的SQL語句如下:

CREATE TABLE #Houses (
    iHouse_ID  int, 
    cName   varchar(50), 
    cNumber   varchar(10), 
    cPhoneNumber1 varchar(25), 
    cAddressLine1 varchar(50), 
    cCity   varchar(30), 
    cStateCode  varchar(2), 
    cZipCode  varchar(10), 
    iUnitsAvailable int, 
    iRegOpsNumber int, 
    cOpsName  varchar(50), 
    iRegionID  int, 
    cRegionName  varchar(50) 
) 

INSERT INTO #Houses (
    iHouse_ID, 
    cName, 
    cNumber, 
    cPhoneNumber1, 
    cAddressLine1, 
    cCity, 
    CStateCode, 
    cZipCode, 
    iUnitsAvailable, 
    iRegOpsNumber, 
    cOpsName, 
    iRegionID, 
    cRegionName) 
SELECT 
    h2.iHouse_ID, 
    h.cName, 
    h.cNumber, 
    h.cPhoneNumber1, 
    h.cAddressLine1, 
    h.cCity, 
    h.CStateCode, 
    h.cZipCode, 
    h.iUnitsAvailable, 
    r.RegOpsNumber, 
    r.opsname, 
    r.iRegion_ID, 
    r.regionname 
FROM rw.fn_GetScopeHouses (@Scope, @dtReport, NULL, NULL, 0) h2 
     JOIN House h on h.iHouse_ID = h2.iHouse_ID 
      AND h.cCompanyID = @CompanyID 
      AND (@GLsubacct IS NULL OR h.iHouse_ID IN ('+ @GLsubacct +')) 
JOIN rw.vw_Reg_Ops r on r.opsareaID = h.iOpsArea_ID 

的問題是,我得到一個錯誤。錯誤信息是...

Error Executing Database Query. 
[Macromedia][SQLServer JDBC Driver][SQLServer]Conversion failed when converting the varchar value '+ @GLsubacct +' to data type int. 

The error occurred in E:\inetpub\wwwroot\intranet\TIPS4\Admin\EFTprocesspullfile.cfm: line 46 

44 :   <cfprocparam type="IN" value="#CompanyID#" DBVARNAME="@CompanyID" cfsqltype="cf_sql_varchar"><!--- TPecku added variable to be passed to the stored Proc ---> 
45 :   <cfif CompanyID EQ 0000> 
46 :   <cfprocparam type="IN" value="#GLsubacct#" DBVARNAME="@GLsubacct" cfsqltype="cf_sql_varchar"> 
47 :   </cfif> 
48 : </cfstoredproc> 

錯誤在存儲過程中,因爲那是我的'+ @GLsubacct +'。 關於我在做什麼的任何想法都是錯誤的? (對不起,很長一段時間,我想盡可能詳細地描述我在做什麼

+2

查看錶值參數(TVP),這可能是您想要使用而不是傳遞字符串。 https://msdn.microsoft.com/en-us/library/bb510489.aspx – rjdevereux

+0

謝謝rjdevereux,我看着你的鏈接,但我仍然困惑於如何前進。 – Tetteh

+1

那麼,你有幾個選擇。一種是使用字符串解析功能。以下是一些你可以做到的方法:https://sqlperformance.com/2012/07/t-sql-queries/split-strings。一種是將表傳遞給存儲過程。要做到這一點,你需要創建一個類型(如上面的鏈接),然後使用它作爲你的過程的'READONLY'參數。無論您選擇什麼選項,您都希望更改您的過程以加入表格(分割值表或您使用的tvp)。 – ZLK

回答

0

爲了使這個工作接近你現有的代碼,你必須創建查詢字符串(替換插入語句)並執行它

我創建了一些虛擬/測試變量來查看查詢是如何使用PRINT語句查找的。 「DECLARE @execQuery varchar(MAX)」到最後替換你的插入語句。

像這樣的邏輯應該用你可以使用的數據填充臨時表#Houses。

-- test variables 
DECLARE @Scope varchar(50), @AcctPeriod char(6), @CompanyID nchar(10), @GLsubacct varchar(1000), @dtReport VARCHAR(20); 
SET @Scope = 'scope'; 
SET @AcctPeriod = 'fall'; 
SET @CompanyID = N'coID'; 
SET @dtReport = 'dtRpt' 
SET @GLsubacct = '123,234,345,456' 

-- copy code below this line 
DECLARE @execQuery varchar(MAX) 

SET @execQuery = 'insert into #Houses (
iHouse_ID, 
cName, 
cNumber, 
cPhoneNumber1, 
cAddressLine1, 
cCity, 
CStateCode, 
cZipCode, 
iUnitsAvailable, 
iRegOpsNumber, 
cOpsName, 
iRegionID, 
cRegionName 
) 
select 
h2.iHouse_ID, 
h.cName, 
h.cNumber, 
h.cPhoneNumber1, 
h.cAddressLine1, 
h.cCity, 
h.CStateCode, 
h.cZipCode, 
h.iUnitsAvailable, 
r.RegOpsNumber, 
r.opsname, 
r.iRegion_ID, 
r.regionname 
FROM rw.fn_GetScopeHouses ('''+ @Scope +''', '''+ @dtReport +''', NULL, NULL, 0) h2 
JOIN House h on h.iHouse_ID = h2.iHouse_ID 
AND h.cCompanyID = N'''+ @CompanyID +'''' 
IF (@GLsubacct IS NOT NULL) 
BEGIN 
    SET @execQuery = @execQuery + ' AND (h.iHouse_ID IN ('+ @GLsubacct +'))' 
END 
SET @execQuery = @execQuery + 'JOIN rw.vw_Reg_Ops r on r.opsareaID = h.iOpsArea_ID' 

--PRINT @execQuery 

EXEC @execQuery 
+0

如果可能,請勿使用動態sql。除了其他問題,它很容易被SQL注入。使用JOIN的udf/table驅動方法會更好。 – Leigh

+0

與cfprocparam標籤cfstoredproc調用不會像cfqueryparam一樣工作嗎? –

+0

如果它是一個常規的SQL語句,執行*沒有* EXEC是。但是,上面構建了一個字面的sql字符串(沒有任何綁定變量)並將其傳遞給EXEC。 (使用PreserveSingleQuotes的SQL等效項的排序)。所以@variables中的任何惡意sql都會被執行。如果您絕對必須使用動態sql,請使用[sp_executeSQL](https://msdn.microsoft.com/zh-cn/library/ms188001.aspx)而不是EXEC。儘管它不適用於所有情況(例如,使用IN子句)。在這種情況下,表格驅動的方法是更好的IMO。 – Leigh

0

我終於想出瞭如何使它工作。在我將這個列表傳遞給存儲過程變量後,我無法直接在我的sql語句中使用這個變量,它不起作用,所以我做的是迭代變量的內容並將它們存儲在一個臨時表中。然後我在我的SQL語句中使用了臨時表的內容。如果你看上面,你會看到我想要做的事情,但沒有成功。我最終做的是......

declare @oneNumber int 
declare @POS int 
if @GLsubacct <> '' 
begin 
--Step through the comma delimted list of numbers and plug each one into a temp table 
create table #HouseList (HouseID int) 
select @POS = patindex('%,%',@GLsubacct) 
while @POS > 0 
begin 
select @oneNumber = cast(left(@GLsubacct,@POS - 1) as int) 
insert into #HouseList (HouseID) values (@oneNumber) 
select @GLsubacct = right(@GLsubacct,len(@GLsubacct) - @POS) 
select @POS = patindex('%,%',@GLsubacct) 
end 
--do the last one which doesn't have any comma 
select @oneNumber = cast(@GLsubacct as int) 
insert into #HouseList (HouseID) values (@oneNumber) 
end 

-- Create #House table 
CREATE TABLE #Houses (
iHouse_ID  int, 
cName   varchar(50), 
cNumber   varchar(10), 
cPhoneNumber1 varchar(25), 
cAddressLine1 varchar(50), 
cCity   varchar(30), 
cStateCode  varchar(2), 
cZipCode  varchar(10), 
iUnitsAvailable int, 
iRegOpsNumber int, 
cOpsName  varchar(50), 
iRegionID  int, 
cRegionName  varchar(50)) 

insert into #Houses (
iHouse_ID, 
cName, 
cNumber, 
cPhoneNumber1, 
cAddressLine1, 
cCity, 
CStateCode, 
cZipCode, 
iUnitsAvailable, 
iRegOpsNumber, 
cOpsName, 
iRegionID, 
cRegionName) 
select 
h2.iHouse_ID, 
h.cName, 
h.cNumber, 
h.cPhoneNumber1, 
h.cAddressLine1, 
h.cCity, 
h.CStateCode, 
h.cZipCode, 
h.iUnitsAvailable, 
r.RegOpsNumber, 
r.opsname, 
r.iRegion_ID, 
r.regionname 
from rw.fn_GetScopeHouses (@Scope, @dtReport, NULL, NULL, 0) h2 
JOIN House h on h.iHouse_ID = h2.iHouse_ID 
AND h.cGLsubaccount IN (select Houseid from #HouseList) 
JOIN rw.vw_Reg_Ops r on r.opsareaID = h.iOpsArea_ID 

它工作完美!

+0

您應該將「分割」邏輯放入UDF表中。那麼你可以在任何列表中使用它,從任何過程 - 不只是這一個:)參見[鏈接ZLK張貼在評論](http://stackoverflow.com/questions/40852635/i-want-to-pass- a-valuelist-to-my-sql-server-stored-procedure#comment68926713_40852635)。 – Leigh

相關問題