我正在尝试为我正在开发的程序创建搜索功能。我现在的查询检查已选择的记录状态,可以是以下任何一种:
然后执行一个select查询,它会提取与这些记录状态匹配的所有记录,这里是查询:
PROCEDURE [dbo].[SearchSQL]
-- Add the parameters for the stored procedure here
@logging_ref as varchar(50) = NULL,
@summit_ac_no as varchar(50) = NULL,
@contract_no as varchar(50) = NULL,
@invoice_no as varchar(50) = NULL,
@company as varchar(50) = NULL,
@paycert as varchar(50) = NULL,
@record_type as integer = NULL,
@qs as varchar(50) = NULL,
@records as int = NULL,
@state as int = NULL
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
IF @state = 1
Begin
SELECT TOP(@records)
-- Reference Columns - Used to identify a Record --
r.r_id AS 'ref',
grossVal AS 'gross',
payCert AS 'cert',
-- Data Columns for Display --
logRef as 'Logging Reference',
db_recTypes.recordName AS 'Record Type',
invNo as 'Invoice No.',
invDate as 'Invoice Date',
accNo as 'Summit Account No.',
db_accountNo.name as 'Company Name',
contract as 'Contract No.',
taxStatus as 'Tax Status',
netVal as 'Net Value',
vat as 'V.A.T',
grossVal as 'Gross Value',
paycert as 'Payment Certificate No.',
period as 'Period',
paydate as 'Anticipated Payment Date',
db_qs.name as 'QS record sent to',
sentDate as 'Date sent to QS',
db_sentMethod.name as 'Sent Via',
returnedDate as 'Date Returned',
r.deleted as 'Removed',
lastModified as 'Last Modified',
creationDate as 'Date Created',
db_users.name as 'Creation User',
p.date as 'Date Paid'
-- Main Table to Reference --
FROM db_records as r
-- Proceed with SQL JOINs --
JOIN db_recTypes
ON db_recTypes.recordID = r.recType
Join db_accountNo
ON db_accountNo.com_id = r.accNo
Join db_qs
On db_qs.q_id = r.sentTo
JOIN db_sentMethod
On db_sentMethod.v_id = r.sentVia
Join db_users
On db_users.u_id = r.u_id
FULL OUTER JOIN db_payments as p
ON p.r_id = r.r_id
-- Check For the following values
WHERE
(@logging_ref IS NULL OR logRef LIKE '%' + @logging_ref + '%')
AND (@summit_ac_no IS NULL OR accNo LIKE '%' + @summit_ac_no + '%')
AND (@contract_no IS NULL OR contract LIKE '%' + @contract_no + '%')
AND (@invoice_no IS NULL OR invNo LIKE '%' + @invoice_no + '%')
AND (@company IS NULL OR db_accountNo.name LIKE '%' + @company + '%')
AND (@paycert IS NULL OR payCert LIKE '%' + @paycert + '%')
AND (@record_type IS NULL OR recType = @record_type)
AND (@qs IS NULL OR db_qs.name LIKE '%' + @qs + '%')
AND r.deleted = 0
END
ELSE
Begin
IF @state = 2
BEGIN
SELECT TOP(@records)
-- Reference Columns - Used to identify a Record --
r.r_id AS 'ref',
grossVal AS 'gross',
payCert AS 'cert',
-- Data Columns for Display --
logRef as 'Logging Reference',
db_recTypes.recordName AS 'Record Type',
invNo as 'Invoice No.',
invDate as 'Invoice Date',
accNo as 'Summit Account No.',
db_accountNo.name as 'Company Name',
contract as 'Contract No.',
taxStatus as 'Tax Status',
netVal as 'Net Value',
vat as 'V.A.T',
grossVal as 'Gross Value',
paycert as 'Payment Certificate No.',
period as 'Period',
paydate as 'Anticipated Payment Date',
db_qs.name as 'QS record sent to',
sentDate as 'Date sent to QS',
db_sentMethod.name as 'Sent Via',
returnedDate as 'Date Returned',
r.deleted as 'Removed',
lastModified as 'Last Modified',
creationDate as 'Date Created',
db_users.name as 'Creation User',
p.date as 'Date Paid'
-- Main Table to Reference --
FROM db_records as r
-- Proceed with SQL JOINs --
JOIN db_recTypes
ON db_recTypes.recordID = r.recType
Join db_accountNo
ON db_accountNo.com_id = r.accNo
Join db_qs
On db_qs.q_id = r.sentTo
JOIN db_sentMethod
On db_sentMethod.v_id = r.sentVia
Join db_users
On db_users.u_id = r.u_id
FULL OUTER JOIN db_payments as p
ON p.r_id = r.r_id
-- Check For the following values
WHERE
(@logging_ref IS NULL OR logRef LIKE '%' + @logging_ref + '%')
AND (@summit_ac_no IS NULL OR accNo LIKE '%' + @summit_ac_no + '%')
AND (@contract_no IS NULL OR contract LIKE '%' + @contract_no + '%')
AND (@invoice_no IS NULL OR invNo LIKE '%' + @invoice_no + '%')
AND (@company IS NULL OR db_accountNo.name LIKE '%' + @company + '%')
AND (@paycert IS NULL OR payCert LIKE '%' + @paycert + '%')
AND (@record_type IS NULL OR recType = @record_type)
AND (@qs IS NULL OR db_qs.name LIKE '%' + @qs + '%')
AND p.date <> null
END
ELSE
BEGIN
IF @state = 3
BEGIN
SELECT TOP(@records)
-- Reference Columns - Used to identify a Record --
r.r_id AS 'ref',
grossVal AS 'gross',
payCert AS 'cert',
-- Data Columns for Display --
logRef as 'Logging Reference',
db_recTypes.recordName AS 'Record Type',
invNo as 'Invoice No.',
invDate as 'Invoice Date',
accNo as 'Summit Account No.',
db_accountNo.name as 'Company Name',
contract as 'Contract No.',
taxStatus as 'Tax Status',
netVal as 'Net Value',
vat as 'V.A.T',
grossVal as 'Gross Value',
paycert as 'Payment Certificate No.',
period as 'Period',
paydate as 'Anticipated Payment Date',
db_qs.name as 'QS record sent to',
sentDate as 'Date sent to QS',
db_sentMethod.name as 'Sent Via',
returnedDate as 'Date Returned',
r.deleted as 'Removed',
lastModified as 'Last Modified',
creationDate as 'Date Created',
db_users.name as 'Creation User',
p.date as 'Date Paid'
-- Main Table to Reference --
FROM db_records as r
-- Proceed with SQL JOINs --
JOIN db_recTypes
ON db_recTypes.recordID = r.recType
Join db_accountNo
ON db_accountNo.com_id = r.accNo
Join db_qs
On db_qs.q_id = r.sentTo
JOIN db_sentMethod
On db_sentMethod.v_id = r.sentVia
Join db_users
On db_users.u_id = r.u_id
FULL OUTER JOIN db_payments as p
ON p.r_id = r.r_id
-- Check For the following values
WHERE
(@logging_ref IS NULL OR logRef LIKE '%' + @logging_ref + '%')
AND (@summit_ac_no IS NULL OR accNo LIKE '%' + @summit_ac_no + '%')
AND (@contract_no IS NULL OR contract LIKE '%' + @contract_no + '%')
AND (@invoice_no IS NULL OR invNo LIKE '%' + @invoice_no + '%')
AND (@company IS NULL OR db_accountNo.name LIKE '%' + @company + '%')
AND (@paycert IS NULL OR payCert LIKE '%' + @paycert + '%')
AND (@record_type IS NULL OR recType = @record_type)
AND (@qs IS NULL OR db_qs.name LIKE '%' + @qs + '%')
AND p.date = null
END
ELSE
Begin
SELECT TOP(@records)
-- Reference Columns - Used to identify a Record --
r.r_id AS 'ref',
grossVal AS 'gross',
payCert AS 'cert',
-- Data Columns for Display --
logRef as 'Logging Reference',
db_recTypes.recordName AS 'Record Type',
invNo as 'Invoice No.',
invDate as 'Invoice Date',
accNo as 'Summit Account No.',
db_accountNo.name as 'Company Name',
contract as 'Contract No.',
taxStatus as 'Tax Status',
netVal as 'Net Value',
vat as 'V.A.T',
grossVal as 'Gross Value',
paycert as 'Payment Certificate No.',
period as 'Period',
paydate as 'Anticipated Payment Date',
db_qs.name as 'QS record sent to',
sentDate as 'Date sent to QS',
db_sentMethod.name as 'Sent Via',
returnedDate as 'Date Returned',
r.deleted as 'Removed',
lastModified as 'Last Modified',
creationDate as 'Date Created',
db_users.name as 'Creation User',
p.date as 'Date Paid'
-- Main Table to Reference --
FROM db_records as r
-- Proceed with SQL JOINs --
JOIN db_recTypes
ON db_recTypes.recordID = r.recType
Join db_accountNo
ON db_accountNo.com_id = r.accNo
Join db_qs
On db_qs.q_id = r.sentTo
JOIN db_sentMethod
On db_sentMethod.v_id = r.sentVia
Join db_users
On db_users.u_id = r.u_id
FULL OUTER JOIN db_payments as p
ON p.r_id = r.r_id
-- Check For the following values
WHERE
(@logging_ref IS NULL OR logRef LIKE '%' + @logging_ref + '%')
AND (@summit_ac_no IS NULL OR accNo LIKE '%' + @summit_ac_no + '%')
AND (@contract_no IS NULL OR contract LIKE '%' + @contract_no + '%')
AND (@invoice_no IS NULL OR invNo LIKE '%' + @invoice_no + '%')
AND (@company IS NULL OR db_accountNo.name LIKE '%' + @company + '%')
AND (@paycert IS NULL OR payCert LIKE '%' + @paycert + '%')
AND (@record_type IS NULL OR recType = @record_type)
AND (@qs IS NULL OR db_qs.name LIKE '%' + @qs + '%')
AND r.deleted = 1
END
END
END
END
似乎导致此问题的表格是db_payments
,因为这是引用记录是否已付款的表格。例如(如果记录尚未支付,则此处不存在)
db_payments
布局为:
p_id - int - Auto Increment
r_id - int - Link to db_records
date - date - date paid
如果您需要db_records
表的布局,我可以发送它。
现在我收到以下错误:
Msg 102, Level 15, State 1, Line 52
Incorrect syntax near 'r'.
以下是程序:
USE [Sub-Con-Dev]
GO
/****** Object: StoredProcedure [dbo].[SearchSQL] Script Date: 22/02/2016 09:17:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Marcus Gloria
-- Create date: 27/01/2016
-- Description: Gets Search Results
-- =============================================
ALTER PROCEDURE [dbo].[SearchSQL]
-- Add the parameters for the stored procedure here
@logging_ref as varchar(50) = NULL,
@summit_ac_no as varchar(50) = NULL,
@contract_no as varchar(50) = NULL,
@invoice_no as varchar(50) = NULL,
@company as varchar(50) = NULL,
@paycert as varchar(50) = NULL,
@record_type as integer = NULL,
@qs as varchar(50) = NULL,
@records as int = NULL,
@state as int = NULL
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX) = N'
SELECT TOP(@records)
r.r_id as ref,
grossVal as gross,
payCert as cert,
p.p_id as paid,
-- Data Columns for Display --
logRef as "Logging Reference",
db_recTypes.recordName AS "Record Type",
invNo as "Invoice No.",
invDate as "Invoice Date",
accNo as "Summit Account No.",
db_accountNo.name as "Company Name",
contract as "Contract No.",
taxStatus as "Tax Status",
netVal as "Net Value",
vat as "V.A.T",
grossVal as "Gross Value",
paycert as "Payment Certificate No.",
period as "Period",
paydate as "Anticipated Payment Date",
db_qs.name as "QS record sent to",
sentDate as "Date sent to QS",
db_sentMethod.name as "Sent Via",
returnedDate as "Date Returned",
r.deleted as "Removed",
lastModified as "Last Modified",
creationDate as "Date Created",
db_users.name as "Creation User",
p.date as "Date Paid"
-- Main Table to Reference --
FROM db_records as r
-- Proceed with SQL JOINs --
JOIN db_recTypes
ON db_recTypes.recordID = r.recType
Join db_accountNo
ON db_accountNo.com_id = r.accNo
Join db_qs
On db_qs.q_id = r.sentTo
JOIN db_sentMethod
On db_sentMethod.v_id = r.sentVia
Join db_users
On db_users.u_id = r.u_id
FULL OUTER JOIN db_payments as p
ON p.r_id = r.r_id
WHERE 1 = 1 '
IF (@logging_ref IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND logRef LIKE ''%'' + @logging_ref'
IF (@summit_ac_no IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND accNo LIKE ''%'' + @summit_ac_no'
IF (@contract_no IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND contract LIKE ''%'' + @contract_no'
IF (@invoice_no IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND invNo LIKE ''%'' + @invoice_no'
IF (@company IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND db_accountNo.name LIKE ''%'' + @company'
IF (@paycert IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND payCert LIKE ''%'' + @paycert'
IF (@record_type IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND recType LIKE ''%'' + @record_type'
IF (@qs IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND db_qs.name LIKE ''%'' + @qs'
DECLARE @lastToken NVARCHAR(100) =
(
CASE
WHEN @state = 1 THEN 'r.deleted = 0'
WHEN @state = 2 THEN 'p.date IS NOT NULL'
WHEN @state = 3 THEN 'p.date IS NULL'
WHEN @state = 4 THEN 'r.deleted =1'
END
)
SET @SQL = @SQL + CHAR(13) + CHAR(10) + @lastToken
EXEC sp_executesql @SQL,
N'@logging_ref as varchar(50), @summit_ac_no as varchar(50) = NULL,
@contract_no as varchar(50), @invoice_no as varchar(50), @company as varchar(50),
@paycert as varchar(50), @record_type as integer, @qs as varchar(50),
@records as int, @state as int',
@records = @records,
@logging_ref = @logging_ref,
@summit_ac_no = @summit_ac_no,
@contract_no = @contract_no,
@invoice_no = @invoice_no,
@company = @company,
@paycert = @paycert,
@record_type = @record_type,
@qs = @qs,
@records = @records,
@state = @state
END
答案 0 :(得分:0)
除了建议使用LEFT JOIN不要错过记录之外,我强烈建议使用动态SQL来简化您的过程。正如现在所写,它违反了DRY principle,很难阅读和理解。
由于您的代码在所有分支上执行相同的操作并且还使用了大量过滤器(至少是虚拟的),因此动态SQL很有可能比过多的OR
更好。此外,该过程要小得多,并且可以轻松实现滤波器或逻辑的任何变化。
注意 :未进行实际测试
CREATE PROCEDURE [dbo].[SearchSQL]
-- Add the parameters for the stored procedure here
@logging_ref as varchar(50) = NULL,
@summit_ac_no as varchar(50) = NULL,
@contract_no as varchar(50) = NULL,
@invoice_no as varchar(50) = NULL,
@company as varchar(50) = NULL,
@paycert as varchar(50) = NULL,
@record_type as integer = NULL,
@qs as varchar(50) = NULL,
@records as int = NULL,
@state as int = NULL
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- no need for alias quotes if they are a full word
-- some comments omitted for brevity
DECLARE @SQL NVARCHAR(MAX) = N'
SELECT TOP(@records)
r.r_id AS ref, grossVal AS gross, payCert AS cert,
-- omitted for brevity
FROM db_records as r
JOIN db_recTypes ON db_recTypes.recordID = r.recType
Join db_accountNo ON db_accountNo.com_id = r.accNo
Join db_qs On db_qs.q_id = r.sentTo
JOIN db_sentMethod On db_sentMethod.v_id = r.sentVia
Join db_users On db_users.u_id = r.u_id
LEFT JOIN db_payments as p ON p.r_id = r.r_id
WHERE 1 = 1 '
IF (@logging_ref IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND logRef LIKE ''%'' + @logging_ref'
IF (@summit_ac_no IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND accNo LIKE ''%'' + @summit_ac_no'
-- other filters come here
IF (@qs IS NOT NULL) SET @SQL = @SQL + CHAR(13) + CHAR(10) + 'AND db_qs = @qs'
DECLARE @lastToken NVARCHAR(100) =
(CASE WHEN @state = 1 THEN 'r.deleted = 0'
WHEN @state = 2 THEN 'p.date <> null'
WHEN @state = 3 THEN 'p.date IS NULL' -- = NULL is not ok
WHEN @state = 4 THEN 'r.deleted = 1'
END) -- what happens if @state is not 1, 2, 3 or 4?
SET @SQL = @SQL + CHAR(13) + CHAR(10) + @lastToken
-- actual execution - PRINT @SQL may be used to check if the query is correct
EXEC sp_executesql @SQL,
N'@records INT, @logging_ref as varchar(50), @summit_ac_no as varchar(50) = NULL,
@contract_no as varchar(50), @invoice_no as varchar(50), @company as varchar(50),
@paycert as varchar(50), @record_type as integer, @qs as varchar(50),
@records as int, @state as int',
@records = @records, @logging_ref = @logging_ref, -- and so on
END
END