Я пробовал это и отлично работал с моим управляемым bean-файлом JSF
ExecutorService executor = Executors.newFixedThreadPool(1);
@EJB
private IMaterialSvc materialSvc;
private void updateMaterial(Material material, String status, Location position) {
executor.execute(new Runnable() {
public void run() {
synchronized (position) {
// TODO update material in audit? do we need materials in audit?
int index = position.getMaterials().indexOf(material);
Material m = materialSvc.getById(material.getId());
m.setStatus(status);
m = materialSvc.update(m);
if (index != -1) {
position.getMaterials().set(index, m);
}
}
}
});
}
@PreDestroy
public void destory() {
executor.shutdown();
}
Принятие никакого аннулирует, Вы GROUP BY
уникальные столбцы, и SELECT
MIN (or MAX)
RowId как строка для хранения. Затем просто удалите все, что не имело идентификатора строки:
DELETE FROM MyTable
LEFT OUTER JOIN (
SELECT MIN(RowId) as RowId, Col1, Col2, Col3
FROM MyTable
GROUP BY Col1, Col2, Col3
) as KeepRows ON
MyTable.RowId = KeepRows.RowId
WHERE
KeepRows.RowId IS NULL
В случае, если у Вас есть GUID вместо целого числа, можно заменить
MIN(RowId)
с
CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
От прикладного уровня (к сожалению). Я соглашаюсь, что надлежащий способ предотвратить дублирование на уровне базы данных с помощью уникального индекса, но в SQL Server 2005, индексу позволяют быть только 900 байтов, и мой varchar (2048), поле сдувает это.
я не знаю, как хорошо это работало бы, но я думаю, что Вы могли записать триггер для осуществления этого, даже если Вы не могли бы сделать этого непосредственно с индексом. Что-то как:
-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism
ON stories
after INSERT, UPDATE
AS
DECLARE @cnt AS INT
SELECT @cnt = Count(*)
FROM stories
INNER JOIN inserted
ON ( stories.story = inserted.story
AND stories.story_id != inserted.story_id )
IF @cnt > 0
BEGIN
RAISERROR('plagiarism detected',16,1)
ROLLBACK TRANSACTION
END
кроме того, varchar (2048) звуки, подозрительные мне (некоторые вещи в жизни составляют 2 048 байтов, но это довольно редко); разве это не должен действительно быть varchar (макс.)?
Вот другая хорошая статья о дубликаты удаления .
Это обсуждает почему его твердое: " SQL основан на алгебре отношений, и дубликаты не могут произойти в алгебре отношений, потому что дубликаты не позволяются в наборе. "
временное решение для таблицы и два mysql примера.
В будущем Вы собирающийся предотвращать его на уровне базы данных, или с точки зрения приложения. Я предложил бы уровень базы данных, потому что Ваша база данных должна быть ответственна за поддержание ссылочной целостности, разработчики просто вызовут проблемы;)
Ну конечно. Используйте временную таблицу. Если Вы хотите сингл, not-very-performant оператор, который "работает", можно пойти с:
DELETE FROM MyTable WHERE NOT RowID IN
(SELECT
(SELECT TOP 1 RowID FROM MyTable mt2
WHERE mt2.Col1 = mt.Col1
AND mt2.Col2 = mt.Col2
AND mt2.Col3 = mt.Col3)
FROM MyTable mt)
В основном, для каждой строки в таблице, подвыбор находит лучший RowID всех строк, которые точно похожи на строку на рассмотрении. Таким образом, Вы заканчиваете со списком RowIDs, которые представляют "исходные" недублированные строки.
Существует хорошая статья о дубликаты удаления на Microsoft Support site. Это довольно консервативно - они сделали, чтобы Вы сделали все на отдельных шагах - но это должно работать хорошо против больших таблиц.
я использовал самосоединения, чтобы сделать это в прошлом, хотя это мог, вероятно, быть prettied с пунктом НАЛИЧИЯ:
DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField
AND dupes.secondDupField = fullTable.secondDupField
AND dupes.uniqueField > fullTable.uniqueField
Создать новую пустую таблицу с той же структурой
Выполнить запрос, подобный этому
INSERT INTO tc_category1
ВЫБРАТЬ *
ОТ tc_category
GROUP BY category_id, application_id
Имея количество (*)> 1
Затем выполните этот запрос
INSERT INTO tc_category1
ВЫБРАТЬ *
ОТ tc_category
GROUP BY category_id, application_id
HAVING count (*) = 1
У меня была таблица, в которой мне нужно было сохранить неповторяющиеся строки. Я не уверен в скорости или эффективности.
DELETE FROM myTable WHERE RowID IN (
SELECT MIN(RowID) AS IDNo FROM myTable
GROUP BY Col1, Col2, Col3
HAVING COUNT(*) = 2 )