iT邦幫忙

0

sql預存程序set問題

  • 分享至 

  • xImage

請問我在預存程序set一個where但這樣裡面的@AcceptDate和@AcceptDate會變成字元串沒辦法轉成datetime
where要怎麼改才能讓他正常轉換?

SQL程式碼

ALTER PROCEDURE [dbo].[GetCheckAccept]
	-- Add the parameters for the stored procedure here
	@CorpNo char(2),
    @AcceptDate datetime,
	@AcceptDate2 datetime,
	@SupplierID char(5)
AS
	DECLARE @statement nvarchar(4000)
	DECLARE @groupby nvarchar(4000)
	DECLARE @where nvarchar(4000)

	SET @statement = 'SELECT cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName,pd.Qty, SUM(DBO.CvtQtyToDec(cd.RealQty)) SendQty 
	FROM IC_CheckAccept c 
	INNER JOIN IC_CheckAcceptDetail cd ON (c.CorpNo=cd.CorpNo AND c.AcceptID=cd.AcceptID)
	INNER JOIN PO_Purchase p ON (cd.CorpNo=p.CorpNo AND cd.PurchaseID=p.PurchaseID)
	INNER JOIN PO_PurchaseDetail pd ON (p.CorpNo=pd.CorpNo AND p.PurchaseID=pd.PurchaseID)
	INNER JOIN PO_Supplier s ON (s.SupplierID=p.SupplierID)'
	
	IF (@SupplierID IS NULL)
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=@AcceptDate and c.AcceptDate<DATEADD ( day,1, @AcceptDate2 ) and c.CorpNo=@CorpNo'
		END
	ELSE
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=@AcceptDate and c.AcceptDate<DATEADD ( day,1, @AcceptDate2 ) and c.CorpNo=@CorpNo and p.SupplierID=@SupplierID'
		END
	SET @groupby = ' GROUP BY cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName, pd.Qty '
SET @statement = @statement + @where + @groupby
exec (@statement)
GO
win895564 iT邦研究生 5 級 ‧ 2022-11-29 10:07:24 檢舉
DECLARE @where [這裡要修改吧?]
不然還是字串型態
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
純真的人
iT邦大師 1 級 ‧ 2022-11-29 10:58:09
最佳解答

你要把動態SQL字串透過sp_executesql 丟@AcceptDate和@AcceptDate參數進去才會是日期~

參考:
https://dotblogs.com.tw/rainmaker/2015/10/01/153472

你要是不丟參數~也是可以轉成字串型態~串到字串裡面再轉時間型態~

ALTER PROCEDURE [dbo].[GetCheckAccept]
	-- Add the parameters for the stored procedure here
	@CorpNo char(2),
    @AcceptDate datetime,
	@AcceptDate2 datetime,
	@SupplierID char(5)
AS
	DECLARE @statement nvarchar(4000)
	DECLARE @groupby nvarchar(4000)
	DECLARE @where nvarchar(4000)

	SET @statement = 'SELECT cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName,pd.Qty, SUM(DBO.CvtQtyToDec(cd.RealQty)) SendQty 
	FROM IC_CheckAccept c 
	INNER JOIN IC_CheckAcceptDetail cd ON (c.CorpNo=cd.CorpNo AND c.AcceptID=cd.AcceptID)
	INNER JOIN PO_Purchase p ON (cd.CorpNo=p.CorpNo AND cd.PurchaseID=p.PurchaseID)
	INNER JOIN PO_PurchaseDetail pd ON (p.CorpNo=pd.CorpNo AND p.PurchaseID=pd.PurchaseID)
	INNER JOIN PO_Supplier s ON (s.SupplierID=p.SupplierID)'
	
	IF (@SupplierID IS NULL)
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=Convert(datetime,''' + Convert(varchar,@AcceptDate,120) + ''') and c.AcceptDate<DATEADD ( day,1, Convert(datetime,''' + Convert(varchar,@AcceptDate2,120) + ''') ) and c.CorpNo=@CorpNo'
		END
	ELSE
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=Convert(datetime,''' + Convert(varchar,@AcceptDate,120) + ''') and c.AcceptDate<DATEADD ( day,1, Convert(datetime,''' + Convert(varchar,@AcceptDate2,120) + ''') ) and c.CorpNo=@CorpNo and p.SupplierID=@SupplierID'
		END
	SET @groupby = ' GROUP BY cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName, pd.Qty '
SET @statement = @statement + @where + @groupby
exec (@statement)
GO
0
allenlwh
iT邦高手 1 級 ‧ 2022-11-29 11:09:59
SET @where = 'WHERE convert(datetime,c.AcceptDate)>=@AcceptDate 
    and convert(datetime,c.AcceptDate)<DATEADD ( day,1, @AcceptDate2 ) 
    and c.CorpNo=@CorpNo'
allenlwh iT邦高手 1 級 ‧ 2022-11-29 11:16:53 檢舉

或是這樣,前端程式不動,傳入的參數還是維持字串,改由接手的預存程序來做型別轉換

ALTER PROCEDURE [dbo].[GetCheckAccept]
	-- Add the parameters for the stored procedure here
	@CorpNo char(2),
    @Date1 varchar(10),
	@Date2 varchar(10),
	@SupplierID char(5)
AS
	DECLARE @statement nvarchar(4000)
	DECLARE @groupby nvarchar(4000)
	DECLARE @where nvarchar(4000)    
    DECLARE @AcceptDate datetime
	DECLARE @AcceptDate2 datetime   
    
    set @AcceptDate=convert(datetime,@Date1)
    set @AcceptDate2=convert(datetime,@Date2)   
    
0
w4560000
iT邦研究生 5 級 ‧ 2022-11-29 13:41:13

可參考組字串方式

SELECT *  
INTO #ATable
FROM
(SELECT 1 AS 'ID', '2022-10-01 00:00:00.000' AS 'CreateDate' UNION
SELECT 2, '2022-11-01 00:00:00.000' UNION
SELECT 3, '2022-12-01 00:00:00.000') data

DECLARE @statement nvarchar(4000), @where nvarchar(4000);

DECLARE @AcceptDate datetime = '2022-11-01 00:00:00.000', @AcceptDate2 datetime = '2022-12-01 00:00:00.000';

SET @where = ' WHERE CreateDate>=''' + CONVERT(VARCHAR(30), @AcceptDate, 121) + ''' and CreateDate<DATEADD ( day,1, ''' + CONVERT(VARCHAR(30), @AcceptDate2, 121) + ''')';

SELECT @statement = 'SELECT * FROM #ATable' + @where
SELECT @statement

EXEC (@statement)

DROP TABLE #ATable
1
alien663
iT邦研究生 3 級 ‧ 2022-11-30 08:59:07

Code

我會這樣寫,把資料用字串傳進去,然後再用datetime去接資料

ALTER PROCEDURE [dbo].[GetCheckAccept]
	-- Add the parameters for the stored procedure here
	@CorpNo char(2),
    @AcceptDate datetime,
	@AcceptDate2 datetime,
	@SupplierID char(5)
AS
	DECLARE @statement nvarchar(4000)
	DECLARE @groupby nvarchar(4000)
	DECLARE @where nvarchar(4000)

	SET @statement = '
	declare @_CorpNo char(2) = ' + @CorpNo + '
    declare @_AcceptDate datetime = ' + (select convert(varchar(30), @AcceptDate)) + '
	declare @_AcceptDate2 datetime = ' + (select convert(varchar(30), @AcceptDate2)) + '
	declare @_SupplierID char(5) = ' + @SupplierID + '

	SELECT cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName,pd.Qty, SUM(DBO.CvtQtyToDec(cd.RealQty)) SendQty 
	FROM IC_CheckAccept c 
	INNER JOIN IC_CheckAcceptDetail cd ON (c.CorpNo=cd.CorpNo AND c.AcceptID=cd.AcceptID)
	INNER JOIN PO_Purchase p ON (cd.CorpNo=p.CorpNo AND cd.PurchaseID=p.PurchaseID)
	INNER JOIN PO_PurchaseDetail pd ON (p.CorpNo=pd.CorpNo AND p.PurchaseID=pd.PurchaseID)
	INNER JOIN PO_Supplier s ON (s.SupplierID=p.SupplierID)'
	
	IF (@SupplierID IS NULL)
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=@_AcceptDate and c.AcceptDate<DATEADD ( day,1, @_AcceptDate2 ) and c.CorpNo=@_CorpNo'
		END
	ELSE
		BEGIN
			SET @where = 'WHERE c.AcceptDate>=@_AcceptDate and c.AcceptDate<DATEADD ( day,1, @_AcceptDate2 ) and c.CorpNo=@_CorpNo and p.SupplierID=@_SupplierID'
		END
	SET @groupby = ' GROUP BY cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName, pd.Qty '
SET @statement = @statement + @where + @groupby
exec (@statement)
GO

個人看法

如果只是這種單純的select語法,其實不建議使用procedure來處理,而是建立view表後,在其他地方根據需求來變換要下的查詢條件,這邊假設是在C#的API端

create view vwCheckAccept
as
SELECT cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName,pd.Qty, SUM(DBO.CvtQtyToDec(cd.RealQty)) SendQty 
	FROM IC_CheckAccept c 
	INNER JOIN IC_CheckAcceptDetail cd ON (c.CorpNo=cd.CorpNo AND c.AcceptID=cd.AcceptID)
	INNER JOIN PO_Purchase p ON (cd.CorpNo=p.CorpNo AND cd.PurchaseID=p.PurchaseID)
	INNER JOIN PO_PurchaseDetail pd ON (p.CorpNo=pd.CorpNo AND p.PurchaseID=pd.PurchaseID)
	INNER JOIN PO_Supplier s ON (s.SupplierID=p.SupplierID)
GROUP BY cd.CorpNo, cd.PurchaseID, cd.PurchaseSeq, cd.MaterialID, p.UseKind, p.SupplierID, s.ShortName, pd.Qty
[HttpPost]
public IActionResult Login([FromBody] MyDataModel payload)
{
    SqlConnection connection = new SqlConnection("my connection string");
    string sql = @" select * from vwCheckAccept
        WHERE c.AcceptDate>=@_AcceptDate and c.AcceptDate<DATEADD ( day,1, @_AcceptDate2 ) and c.CorpNo=@_CorpNo";
    sql += string.isNullOrEmpty(payload.SupplierID)? : "" : " and p.SupplierID=@_SupplierID";
    connection.Open();
    var data = connection.Query(sql, new { payload.CorpNo, payload.AcceptDate, payload.AcceptDate2, payload.SupplierID });
    connection.Close();
    connection.Dispose();
    return Ok( new { data });
}

謝謝分享
我本來也沒打算用procedure來處理,是需求單下來後主管要求的/images/emoticon/emoticon06.gif

我要發表回答

立即登入回答