SQL 服务器函数处理搜索表单提交和 return table 值的逻辑问题

Logic issue in SQL Server function to handle search form submission and return table value

我在 java 网络应用程序中构建了一个搜索表单,如下图所示

现在,此页面的用户需要在 6 个搜索字段中的一个或多个中输入值,或者可以进行开放式搜索,将所有字段留空。

我有以下函数获取结果。

USE [KingsBayY]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[test_fn_transaction_search]
   (@receiptnum varchar(4001) ='',--00040401010000021
    @account varchar(4001) ='',
    @FN varchar(4001) ='',
    @ln varchar(4001) ='',--DateTime = '',
    @dt varchar(4001) ='',
    @program varchar(4001) ='',--)
    @attendee varchar(4001) =''
)
    --stdt
    --enddt
RETURNS @resulttable TABLE
   (trid  int,
    trdate   varchar(4001), --COLLATE database_default
    tramount       money,
    trinvoice  varchar(4001),
    trcashierid varchar(4001),
    trvoided varchar(4001),
    trrecallid varchar(4001),
    trrecalltype varchar(4001),
    trattendee varchar(4001),
    trperiod varchar(4001),
    stopbilling varchar(4001),
    caccount varchar(4001),
    firstname varchar(4001),
    lastname varchar(4001),
    trprogram varchar(4001),
    itemlookupcode varchar(4001),
    paydate varchar(4001)
    )
AS
BEGIN
IF (@receiptnum='' and @account='' and @FN=''and @ln='' and @dt='' and @program='' and @attendee='')
    INSERT INTO @resulttable
    select tr.ID AS [Transaction ID], tr.Time AS [trDt], tr.Total AS [amount], 
            tr.ReceiptNumber AS [invoice], tr.CashierID AS [cashid], 
            tr.Voided AS [voided], tr.RecallID AS [recallid], tr.RecallType AS [recalltype], 
            tr.Comment AS [attendee], tr.ReferenceNumber AS [trperiod], tr.StopBilling  AS [stopbilling],
            --fields from customer
            c.AccountNumber AS [accountnum], c.FirstName AS [firstname], c.LastName AS [lastname],
            --fields from item
            it.Description AS [programname], it.ItemLookupCode AS [trItemLookupCode],
            --fields from tenderentry
            tent.PaymentDate AS [paydate]

     from "Transaction" tr, TransactionEntry trent, Item it, Customer c, TenderEntry tent
     where trent.TransactionID = tr.ID
     and tent.TransactionID = tr.ID
     and trent.ItemID = it.ID
     and c.ID=tr.CustomerID
     and tr.RecallID =0 --parent
     --and tr.RecallType=0 --parent transactions and independant sales

     order by tr.id, tr.time;
else IF (@receiptnum<>'' or @account<>'' or @FN<>'' or @ln<>'' or @dt<>'' or @program<>'' or @attendee<>'')
    INSERT INTO @resulttable
    select tr.ID AS [Transaction ID], tr.Time AS [trDt], tr.Total AS [amount], 
            tr.ReceiptNumber AS [invoice], tr.CashierID AS [cashid], 
            tr.Voided AS [voided], tr.RecallID AS [recallid], tr.RecallType AS [recalltype], 
            tr.Comment AS [attendee], tr.ReferenceNumber AS [trperiod], tr.StopBilling  AS [stopbilling],
            --fields from customer
            c.AccountNumber AS [accountnum], c.FirstName AS [firstname], c.LastName AS [lastname],
            --fields from item
            it.Description AS [programname], it.ItemLookupCode AS [trItemLookupCode],
            --fields from tenderentry
            tent.PaymentDate AS [paydate]

     from "Transaction" tr, TransactionEntry trent, Item it, Customer c, TenderEntry tent
     where trent.TransactionID = tr.ID
     and tent.TransactionID = tr.ID
     and trent.ItemID = it.ID
     and c.ID=tr.CustomerID
     and tr.RecallID =0 --parent transactions and independant sales
     --and tr.RecallType=0 --
     and(
     tr.ReceiptNumber=ISNULL(@receiptnum,tr.ReceiptNumber)--invoice
     or c.accountnumber=ISNULL(@account,c.accountnumber)--account
     or c.FirstName=ISNULL(@FN, c.FirstName)
     or c.LastName=ISNULL(@ln, c.LastName)--customer
     or tr.time=ISNULL(@dt,tr.time)--date
     or tr.Comment=ISNULL(@attendee,tr.Comment)
     --program
     )
     union
     select tr.ID AS [Transaction ID], tr.Time AS [trDt], tr.Total AS [amount], 
            tr.ReceiptNumber AS [invoice], tr.CashierID AS [cashid], 
            tr.Voided AS [voided], tr.RecallID AS [recallid], tr.RecallType AS [recalltype], 
            tr.Comment AS [attendee], tr.ReferenceNumber AS [trperiod], tr.StopBilling  AS [stopbilling],
            --fields from customer
            c.AccountNumber AS [accountnum], c.FirstName AS [firstname], c.LastName AS [lastname],
            --fields from item
            it.Description AS [programname], it.ItemLookupCode AS [trItemLookupCode],
            --fields from tenderentry
            tent.PaymentDate AS [paydate]

     from "Transaction" tr, TransactionEntry trent, Item it, Customer c, TenderEntry tent
     where trent.TransactionID = tr.ID
     and tent.TransactionID = tr.ID
     and trent.ItemID = it.ID
     and c.ID=tr.CustomerID
     and tr.RecallID =0 --parent transactions and independant sales
     --and tr.RecallType=0 --
     and(
     ISNULL(tr.ReceiptNumber,'1')= ISNULL(@receiptnum,'1')--invoice
     and ISNULL(c.accountnumber,'1')= ISNULL(@account,'1')--account
     and ISNULL(c.FirstName,'1')= ISNULL(@FN,'1')
     and ISNULL(c.LastName,'1')= ISNULL(@ln,'1')--customer
     and ISNULL(tr.time,'1')= ISNULL(@dt,'1')--date
     and ISNULL(tr.Comment,'1')=ISNULL(@attendee,tr.Comment)
     --program
     )
     order by tr.id, tr.time;
RETURN
END

我从这个过程中得到了错误的结果。我注意到的问题是,

  1. 无论如何尝试搜索.. 打开搜索,指定一个搜索参数.. 指定多个搜索参数值,程序 return 的所有结果。如何根据使用的搜索参数将其编辑为 return 仅结果?

  2. 一些搜索参数可能不完全匹配..例如参加者字段..用户可能输入 'John Doe' 而 table 有参加者列其中一个单元格值为 'John Doe - the genius'.. 我希望能够搜索在单元格值中输入的术语。我该怎么做。

这是catch-all query的一种。


ALTER FUNCTION [dbo].[test_fn_transaction_search]    
(
   @receiptnum      VARCHAR(4001) =     NULL,
    @account        VARCHAR(4001) =     NULL,
    @FN             VARCHAR(4001) =     NULL,
    @ln             VARCHAR(4001) =     NULL,
    @dt             VARCHAR(4001) =     NULL,
    @program        VARCHAR(4001) =     NULL,
    @attendee       VARCHAR(4001) =     NULL
)
RETURNS @resulttable TABLE
(
    trid            INT,
    trdate          VARCHAR(4001),
    tramount        MONEY,
    trinvoice       VARCHAR(4001),
    trcashierid     VARCHAR(4001),
    trvoided        VARCHAR(4001),
    trrecallid      VARCHAR(4001),
    trrecalltype    VARCHAR(4001),
    trattendee      VARCHAR(4001),
    trperiod        VARCHAR(4001),
    stopbilling     VARCHAR(4001),
    caccount        VARCHAR(4001),
    firstname       VARCHAR(4001),
    lastname        VARCHAR(4001),
    trprogram       VARCHAR(4001),
    itemlookupcode  VARCHAR(4001),
    paydate         VARCHAR(4001)
)
AS
BEGIN  
    
    INSERT INTO @resulttable
        SELECT 
            tr.ID AS [Transaction ID],
            tr.Time AS [trDt],
            tr.Total AS [amount], 
            tr.ReceiptNumber AS [invoice],
            tr.CashierID AS [cashid], 
            tr.Voided AS [voided],
            tr.RecallID AS [recallid],
            tr.RecallType AS [recalltype], 
            tr.Comment AS [attendee],
            tr.ReferenceNumber AS [trperiod],
            tr.StopBilling  AS [stopbilling],            
            c.AccountNumber AS [accountnum],
            c.FirstName AS [firstname],
            c.LastName AS [lastname],
            it.Description AS [programname],
            it.ItemLookupCode AS [trItemLookupCode],
            tent.PaymentDate AS [paydate]
     FROM [Transaction] tr
     INNER JOIN TransactionEntry trent
        ON trent.TransactionID = tr.ID
     INNER JOIN Item it
        ON trent.ItemID = it.ID
     INNER JOIN Customer c
        ON c.ID=tr.CustomerID
     INNER JOIN TenderEntry tent
        ON tent.TransactionID = tr.ID
     WHERE
        tr.RecallID = 0
        AND (tr.ReceiptNumber = @receiptnum OR @receiptnum IS NULL)
        AND (c.accountnumber = @account OR @account IS NULL)
        AND (c.FirstName = @FN OR @FN IS NULL)
        AND (c.LastName = @ln OR @ln IS NULL)
        AND (tr.time = @dt OR @dt IS NULL) 
        AND (tr.Comment LIKE @attendee + '%' OR @attendee IS NULL)

RETURN
END

备注:

  1. 尝试为没有值的字段传递 NULL 而不是 ''
  2. Stop using the old-style JOIN
  3. 也许应该是 ITVF 而不是 MTVF。