#sql #sql-update
#sql #sql-update
Вопрос:
Мне нужно обновить только одну запись в базе данных и назначить ее пользователю. Вот что я делаю:
UPDATE TOP (1) books SET assigneduser = 1
WHERE bookstatus = 7
AND ((assigneduser is null) or (assigneduser = 1));
У меня также есть поле с именем bookname, которое я бы предпочел упорядочить по, но update, похоже, его не поддерживает.
Также обратите внимание, что у меня будет 50 пользователей, использующих программное обеспечение одновременно, поэтому мне нужно будет убедиться, что только одному пользователю назначена книга. В противном случае я бы сначала запустил select, а затем обновил верхнюю запись.
Спасибо.
Комментарии:
1. Не могли бы вы сообщить нам, какую СУБД вы используете?
Ответ №1:
Вы должны сначала выбрать нужную запись, затем обновить ее:
update books
set assigneduser = 1
where BookPrimaryKeyField = (
SELETE TOP 1 BookPrimaryKeyField
from books
WHERE bookstatus = 7
AND ((assigneduser is null) or (assigneduser = 1));
)
Ответ №2:
Если вы хотите обновить только одну строку в базе данных, лучший способ сделать это — выяснить, каков ее первичный ключ, и использовать его. Вы можете сделать это, сказав
UPDATE books SET assigneduser = 1
WHERE BOOKID
= (SELECT top 1 BOOKID FROM books where
bookstatus = 7
AND ((assigneduser is null) or (assigneduser = 1)));
Комментарии:
1. @Adrian — Я так не думаю, я удалил это из своего sql, это был остаток от copy’n’paste — спасибо!
Ответ №3:
UPDATE B
SET assigneduser = 1
FROM books B
WHERE bookstatus = 7
AND ((assigneduser is null) or (assigneduser = 1))
and bookid = (select min(bookid) from books where assigneuser is null)
Я предположил, что у вас есть столбец идентификатора bookid.
Это позволяет получить наименьший идентификатор книги без назначенного пользователя и присоединить его обратно к книгам, чтобы получить единственную запись (как часть b), которую вы затем можете обновить.
Ответ №4:
Посмотрите на http://msdn.microsoft.com/en-us/library/ms177523.aspx.
Если вы должны использовать TOP для применения обновлений в значимой хронологии, вы должны использовать TOP вместе с ORDER BY в инструкции subselect . Следующий пример обновляет часы отпуска 10 сотрудников с самыми ранними датами найма.
UPDATE HumanResources.Employee
SET VacationHours = VacationHours 8
FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee
ORDER BY HireDate ASC) AS th
WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;
GO
Ответ №5:
Вероятно, было бы проще разбить это на 2 части
DECLARE @bookid as INT
SELECT TOP (1) @bookid = id FROM books
WHERE bookstatus = 7
AND ((assigneduser is null) or (assigneduser = 1))
ORDER BY bookname
UPDATE books SET assigneduser = 1
WHERE id = @bookid
Ответ №6:
Есть способ обойти это, используя следующий подзапрос:
UPDATE books SET assigneduser=1
AND ((assigneduser is null) or (assigneduser = 1))
AND bookname in (SELECT TOP 1 bookname FROM Table ORDER BY bookname DESC)
Комментарии:
1. @Adrian: Просто из любопытства — как вы думаете, в чем ошибка
UPDATE TOP(1)
? Кажется, у меня это работает (при условии, что это SQLServer)2. @a1ex07, это будет зависеть от того, какую версию базы данных вы используете, будет ли это работать.
3. У меня это также работает в SQL Server 2008. Однако OP не указал RDMS. Утверждать, что это работает, рискованно. Вот почему я спросил «вы уверены», вместо «это неправильно». Кстати, я не знаю, будет ли это работать на SQL Server 2005 или меньше
4. @Adrian: Да, я понимаю… У меня нет SQLServer 2005, но, согласно msdn, он также должен работать. В любом случае, то, что вы говорите, имеет смысл — это может не работать в более старых версиях или на разных RDMS.
5. Вот и все, ребята. Кроме того, при использовании
TOP
важен порядок, о чем спрашивает OP: как убедиться, что вы обновляете правильную запись? Кстати, мой ответ делает это в стиле ANSI SQL.
Ответ №7:
Поскольку update не возвращает никаких данных, а ‘order by’ сортирует результирующий набор, ORDER BY
работать не над чем, и то, что вы ищете, невозможно.
Если вы хотите назначить только одну книгу, вы можете обновить, используя join в top 1 из вашего набора.
UPDATE b0 SET assigneduser = 1
FROM b0
INNER JOIN
(SELECT top 1 id FROM books
WHERE user = 1 OR user is null
AND status =7) b1 ON b1.id = b0.id
или, возможно, менее загадочный
UPDATE user SET assigneduser = 1
WHERE id IN
(SELECT top 1 id FROM books
WHERE user = 1 OR user is null
AND status =7) b1 ON b1.id = b0.id
Является ли эта стратегия надежной в отношении параллелизма, зависит от семантики транзакции.