Я решил локальный postgresql и отключил
'sudo service postgresql stop
sudo update-rc.d postgresql disable'
В то время как COALESCE
прием аккуратен, мой предпочтительный метод:
CREATE PROCEDURE ps_Customers_SELECT_NameCityCountry
@Cus_Name varchar(30) = NULL
,@Cus_City varchar(30) = NULL
,@Cus_Country varchar(30) = NULL
,@Dept_ID int = NULL
,@Dept_ID_partial varchar(10) = NULL
AS
SELECT Cus_Name
,Cus_City
,Cus_Country
,Dept_ID
FROM Customers
WHERE (@Cus_Name IS NULL OR Cus_Name LIKE '%' + @Cus_Name + '%')
AND (@Cus_City IS NULL OR Cus_City LIKE '%' + @Cus_City + '%')
AND (@Cus_Country IS NULL OR Cus_Country LIKE '%' + @Cus_Country + '%')
AND (@Dept_ID IS NULL OR Dept_ID = @DeptID)
AND (@Dept_ID_partial IS NULL OR CONVERT(varchar, Dept_ID) LIKE '%' + @Dept_ID_partial + '%')
Подобные SPS может легко быть сгенерированным кодом (и повторно созданный для изменений таблицы).
У Вас есть несколько опций для обработки чисел - зависящий, если Вы хотите точную семантику или поисковую семантику.
Самый эффективный способ реализовать этот тип поиска с хранимой процедурой. Оператор, показанный здесь, создает процедуру, которая принимает обязательные параметры. Когда значение параметра не предоставляется, оно устанавливается в NULL.
CREATE PROCEDURE ps_Customers_SELECT_NameCityCountry
@Cus_Name varchar(30) = NULL,
@Cus_City varchar(30) = NULL,
@Cus_Country varchar(30) =NULL
AS
SELECT Cus_Name,
Cus_City,
Cus_Country
FROM Customers
WHERE Cus_Name = COALESCE(@Cus_Name,Cus_Name) AND
Cus_City = COALESCE(@Cus_City,Cus_City) AND
Cus_Country = COALESCE(@Cus_Country,Cus_Country)
Взятый от этой страницы: http://www.sqlteam.com/article/implementing-a-dynamic-where-clause
Я сделал это прежде. Это работает хорошо.
Статья Dynamic Search Conditions Erland Sommarskog в T-SQL является хорошей ссылкой о том, как сделать это. Erland представляет много стратегий относительно того, как сделать это, не используя динамический SQL (просто, ЕСЛИ блоки, ИЛИ, ОБЪЕДИНЯЮТ, и т.д.), и даже перечисляет рабочие характеристики каждой техники.
В случае, если необходимо стиснуть зубы и пройти Динамический путь SQL, необходимо также считать Проклятие Erland и Благословения Динамического SQL, где он выделяет некоторые подсказки относительно того, как правильно записать динамический SQLs
Это может быть сделано, но обычно эти процедуры раковины результат в некоторых плохих планах запросов.
Сказав все это, вот тактика, обычно используемая для "дополнительных" параметров. Нормальный подход должен рассматривать ПУСТОЙ УКАЗАТЕЛЬ как "ommitted".
SELECT
E.EmployeeID,
E.LastName,
E.FirstName
WHERE
E.FirstName = COALESCE(@FirstName, E.FirstName) AND
E.LastName = COALESCE(@LastName, E.LastName) AND
E.DepartmentID = COALESCE(@DepartmentID, E.DepartmentID)
Править: Намного лучший подход был бы параметризированными запросами. Вот сообщение в блоге от одних из передовых полномочий в мире в этом домене, Frans Bouma от LLBLGen Pro известность:
Используя ОБЪЕДИНИТЬ метод имеет проблему в том, что, если Ваш столбец имеет Нулевое значение, передающее в ПУСТОМ условии поиска (значение игнорируют условие поиска) не возвратит строку во многих базах данных.
Например, попробуйте следующий код SQL Server 2000:
CREATE TABLE dbo.Test_Coalesce (
my_id INT NOT NULL IDENTITY,
my_string VARCHAR(20) NULL )
GO
INSERT INTO dbo.Test_Coalesce (my_string) VALUES (NULL)
INSERT INTO dbo.Test_Coalesce (my_string) VALUES ('t')
INSERT INTO dbo.Test_Coalesce (my_string) VALUES ('x')
INSERT INTO dbo.Test_Coalesce (my_string) VALUES (NULL)
GO
DECLARE @my_string VARCHAR(20)
SET @my_string = NULL
SELECT * FROM dbo.Test_Coalesce WHERE my_string = COALESCE(@my_string, my_string)
GO
Вы только возвратите две строки, потому что в строках, где столбец my_string является ПУСТЫМ, Вы - эффективное получение:
my_string = COALESCE(@my_string, my_string) =>
my_string = COALESCE(NULL, my_string) =>
my_string = my_string =>
NULL = NULL
Но конечно, ПУСТОЙ УКАЗАТЕЛЬ не равняется ПУСТОМУ УКАЗАТЕЛЮ.
Я пытаюсь придерживаться с:
SELECT
my_id,
my_string
FROM
dbo.Test_Coalesce
WHERE
(@my_string IS NULL OR my_string = @my_string)
Конечно, можно скорректировать это для использования подстановочных знаков или независимо от того, что Вы хотите сделать.
Моя первая мысль состояла в том, чтобы записать запросу что-то вроде этого...
SELECT EmpId, NameLast, NameMiddle, NameFirst, DepartmentName
FROM dbo.Employee
INNER JOIN dbo.Department ON dbo.Employee.DeptId = dbo.Department.Id
WHERE IdCrq IS NOT NULL
AND
(
@bitSearchFirstName = 0
OR
Employee.NameFirst = @vchFirstName
)
AND
(
@bitSearchMiddleName = 0
OR
Employee.NameMiddle = @vchMiddleName
)
AND
(
@bitSearchFirstName = 0
OR
Employee.NameLast = @vchLastName
)
AND
(
@bitSearchDepartment = 0
OR
Department.Id = @intDeptID
)
... который затем сделал бы, чтобы вызывающая сторона обеспечила немного флага, если они хотят искать конкретное поле и затем предоставить значение, если они должны искать его, но я не знаю, создает ли это неаккуратный оператор Where или если мне может сойти с рук Оператор выбора в операторе Where.
Поскольку Вы видите, что этот конкретный код находится в T-SQL, но я с удовольствием посмотрю на некоторый мн SQL / код MySQL также и адаптируюсь соответственно.
Я придерживался бы АННУЛИРОВАТЬ/ОБЪЕДИНЯТЬ метода по Специальным запросам и затем протестировал бы, чтобы удостовериться, что у Вас нет проблем производительности.
Если оказывается, что у Вас есть медленные рабочие запросы, потому что это делает сканирование таблицы, когда Вы ищете на столбцах, которые индексируются, Вы могли всегда добавлять универсальную поисковую хранимую процедуру с дополнительными определенными, которые позволяют искать на этих индексируемых полях. Например, у Вас мог быть специальный SP, который делает поиски CustomerID или Последнее / Имя.