Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.08.2014, 21:20   #1
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию Базы данных: изменить N "первых" строк таблицы

САБЖ, но не первых.

Есть таблица, пускай вот такая:
Код:
CREATE TABLE levels (
        nset INT NOT NULL, 
        nlevel INT NOT NULL, 
        status INT NOT NULL, 
        PRIMARY KEY (nset, nlevel)
);
Мне надо отсортировать таблицу по двум полям (nset, nlevel) и в N (пусть 5 для примера) первых таких строк, что status = 0, изменить статус.

Как это сделать, не вводя дополнительно еще одно поле (ID)? Т.е. я хочу использовать составной ключ.

Делаю примерно так (не работает)
Код:
UPDATE levels 
SET status = 1
WHERE (nset, nlevel) IN (
    SELECT nset, nlevel FROM levels
    WHERE status = 0
    ORDER BY nset, nlevel
    LIMIT 5
)
Ну понятно, что это не работает, т.к. IN копает множество, а у нас получается таблица из двух колонок.

Можно ли как-то обойтись без добавления ключа (несоставного)?

SQLite, но если знаете как это сделать в других SQL - пишите, интересно.
rrrFer вне форума Ответить с цитированием
Старый 03.08.2014, 21:52   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Хм... з0ддачка...
Ладно, моя тактика: Создаем процедуру. В процедуре делаем селект
Код:
    SELECT nset, nlevel FROM levels
    WHERE status = 0
    ORDER BY nset, nlevel
    LIMIT 5
Это у тя есть.
После делает FETCH по этому селекту. В цикле уже будет тот самый
Код:
UPDATE levels 
SET status = 1
WHERE nset=Переменка1, nlevel=Переменка2
Переменки ессно из фетча.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 04.08.2014, 06:11   #3
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Спасибо, подумаю над этим. Я FETCH никогда не пользовал и не понял что это, во всяких поделках оракла есть ключевое слово FETCH, но в sqlite нету вроде бы.

Вот тут: http://www.opennet.ru/base/dev/sqlite_guide.txt.html

пример такой:
Цитата:
while ($row = sqlite_fetch_array($result)) {
print_r($row);
/* каждый результат будет выглядеть примерно так
Array
(
[0] => 1
[id] => 1
[1] => Ilia
[name] => Ilia
)
*/
Короче это снаружи запроса надо код писать на каком-нибудь С++, я так нехочу, этож ужасно.

Я таки добавил ID и решил так:
Код:
    UPDATE levels
    SET status = 1
    WHERE id IN (
      SELECT id FROM levels 
      WHERE status = 0
      ORDER BY nset, nlevel 
      LIMIT 5
    )
Странно что составной ключ дает такой гемморой. Из за добавления ID, я так понимаю у меня в БД появились транзитивные зависимости, а значит база уже не находится даже в третьей нормальной форме. Вот такие вот дела. Хотя лично мне кажется, что из за того, что транзитивные зависимости между ключевыми полями (возможными ключами), то беды нет и проблем с обновлением базы тоже (хотя в матчасти SQL я таких сносок не видел).

Вариант с Фетчем 100% не оптимален адски.

Последний раз редактировалось rrrFer; 04.08.2014 в 06:15.
rrrFer вне форума Ответить с цитированием
Старый 04.08.2014, 12:15   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

На сиквеле так можно, если не заморачиваться с FETCH
Код:
UPDATE SprMain
  SET User_Date='20140804 07:10:00'
  FROM SprMain S1,(SELECT TOP 10 NomSpr,Kod FROM SprMain WHERE User_Id=10 ORDER BY NomSpr,Kod) S2
  WHERE S1.NomSpr=S2.NomSpr AND S1.Kod=S2.Kod
Код:
UPDATE SprMain
  SET User_Date='20140804 07:13:00'
  WHERE NomSpr*1000+Kod IN (SELECT TOP 10 NomSpr*1000+Kod FROM SprMain WHERE User_Id=10 ORDER BY NomSpr,Kod)
Первый вариант фишка сиквела, навряд-ли sqlite съест, а второй должен пройти с учетом типа и размерности NomSpr и Kod. И самой собой LIMIT вместо TOP
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 04.08.2014 в 12:17.
Аватар вне форума Ответить с цитированием
Старый 04.08.2014, 12:20   #5
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

ыы, но второе - это грязный трюк, опасно это.
rrrFer вне форума Ответить с цитированием
Старый 04.08.2014, 12:23   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Если составной ключ, то и с умом сделанная суперпозиция от него тоже ключем останется. Грязи особой и не вижу
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 04.08.2014, 12:54   #7
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Если составной ключ, то и с умом сделанная суперпозиция от него тоже ключем останется. Грязи особой и не вижу
Но, я пытался конкатенацию делать, но в SQLite CONCAT вообще не работает, а на то, что работает есть какие-то хитрые ограничения ).

Пасибо вцелом, я думал в SQL есть что-то типа кортежей. Походу нету )
rrrFer вне форума Ответить с цитированием
Старый 04.08.2014, 15:54   #8
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Дока SQLite пишет, что он понимает with:
Код:
with t as (
  select nset, nlevel from levels
  where status = 0
  order by nset, nlevel
  limit 5
)
update
  levels
set
  status = 1
where
  nset = t.nset and nlevel = t.nlevel;
Цитата:
Сообщение от rrrFer Посмотреть сообщение
Пасибо вцелом, я думал в SQL есть что-то типа кортежей. Походу нету )
Кортежи в SQL -- это составные ключи. Степень их поддержки зависит от сервера, видимо.
Vapaamies вне форума Ответить с цитированием
Старый 05.08.2014, 07:10   #9
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Вместо FETCH (выбор по курсору же, да?) можно юзать цикОл с табличной переменной (на крайний - с временной таблицей), пример на сиквеле:
Код:
DECLARE @records TABLE(id int identity(1,1), nset int , nlevel int)
DECLARE
	@max int,
	@step int,
	@nset int,
	@nlevel int,
	@status int
	
INSERT @records 
SELECT TOP 5 nset, nlevel 
FROM levels
WHERE status = 0
ORDER BY nset, nlevel
  
SELECT @max = COUNT(id) FROM @records
SELECT @step = 1

WHILE @step <= @max
BEGIN
	SELECT @nset = nset, @nlevel = nlevel
	FROM @records
	WHERE id = @step
	
	UPDATE levels 
	SET status = 1
	WHERE nset = @nset AND nlevel = @nlevel		
	
	SELECT @step = @step + 1
END
Но вариант с Update from join ( у Аватара который через запятые) получше конечно будет, можно поглядеть аналоги.

Последний раз редактировалось phomm; 05.08.2014 в 07:22.
phomm вне форума Ответить с цитированием
Старый 06.08.2014, 10:44   #10
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Цитата:
Сообщение от phomm Посмотреть сообщение
Вместо FETCH (выбор по курсору же, да?) можно юзать цикОл с табличной переменной (на крайний - с временной таблицей), пример на сиквеле:
Это всё жуткая жуть, корявая и непортируемая. Под каждый сервер придется писать ее заново. Вариант же с with имеется в стандарте, и точно будет работать в SQLite и Oracle, скорее всего в PostgreSQL, и вероятно даже в MySQL. Да и в MS SQL я рекомендовал бы заглянуть лишний раз в доку. Начиная с 2008-й версии они понадобавляли много всего стандартного, те же аналитические функции, например.

Короче, with -- это стандартный стандарт, в противоположность жуткой жути.
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нужно создать "батник", вырезать из "2.txt" первых n строк и вставить их в "1.txt" temphard Помощь студентам 2 03.09.2013 16:03
Ошибка при работе с БД: "Нераспознаваемый формат базы данных" lutdan БД в Delphi 7 21.03.2013 09:47
Русские буквы "o", "e", "c", "a" изменить на соответствующие английские буквы ramm159 Общие вопросы Delphi 3 25.12.2012 20:29
Нубо - вопрос, составление Базы Данных "планирование загрузки пр-ва" zitruskiller Microsoft Office Access 10 26.10.2011 12:34
выполнить пять лабораторных работ по дисциплине "Базы данных" ai\ekcah^p Фриланс 4 28.01.2010 09:59