Форум пользователей MySQL
Всем привет! Возникла ситуация не удалять ничего а помечать как удаленные. Собственно вопрос как это можно сделать с помощью триггеров, чтоб он помечал is_delete=1 и не удалял при DELETE
И вопрос можно ли чтоб он не учитывался при SELECT UPDATE это глупость и сказа конечно. Но это решило бы все проблемы.
Отредактированно nekulin (10.10.2012 16:30:44)
#2 10.10.2012 16:49:04
vasya Архат Откуда: Орел Зарегистрирован: 07.03.2007 Сообщений: 5821
Re: не удалять а помечать как удаленные
nekulin написал:
Всем привет! Возникла ситуация не удалять ничего а помечать как удаленные. Собственно вопрос как это можно сделать с помощью триггеров, чтоб он помечал is_delete=1 и не удалял при DELETE
А почему не сделать update вместо delete?
nekulin написал:
И вопрос можно ли чтоб он не учитывался при SELECT UPDATE это глупость и сказа конечно. Но это решило бы все проблемы.
Не понял смысл предложения.
#3 10.10.2012 17:07:56
nekulin Завсегдатай Зарегистрирован: 06.04.2012 Сообщений: 56
Re: не удалять а помечать как удаленные
vasya написал:
nekulin написал:
Всем привет! Возникла ситуация не удалять ничего а помечать как удаленные. Собственно вопрос как это можно сделать с помощью триггеров, чтоб он помечал is_delete=1 и не удалял при DELETE
А почему не сделать update вместо delete?
Потому что придется переделывать много функционала
nekulin написал:
И вопрос можно ли чтоб он не учитывался при SELECT UPDATE это глупость и сказа конечно. Но это решило бы все проблемы.
Не понял смысл предложения.
Это глупый вопрос, но все же.
если мы у записи указали is_delete=1 то он не должен ее выдавать в результате при select and update
#4 10.10.2012 23:31:30
vasya Архат Откуда: Орел Зарегистрирован: 07.03.2007 Сообщений: 5821
Re: не удалять а помечать как удаленные
nekulin написал:
Потому что придется переделывать много функционала
А придется.
Можно попробовать извратиться:
тригерр before delete добавляет/изменяет данные во второй таблице, после чего вылетает с ошибкой (signal), т.о. отменяя удаление.
во второй таблице триггер изменяет данные в первой (is_delete=1)
Но это вариант — гланды через задницу.
nekulin написал:
Это глупый вопрос, но все же.
если мы у записи указали is_delete=1 то он не должен ее выдавать в результате при select and update
select . where is_delete=0;
Или, если не хотите переделывать функционал, то можно попробовать через view, но там есть масса ограничений.
#5 10.10.2012 23:36:21
nekulin Завсегдатай Зарегистрирован: 06.04.2012 Сообщений: 56
Re: не удалять а помечать как удаленные
vasya написал:
nekulin написал:
Потому что придется переделывать много функционала
А придется.
Можно попробовать извратиться:
тригерр before delete добавляет/изменяет данные во второй таблице, после чего вылетает с ошибкой (signal), т.о. отменяя удаление.
во второй таблице триггер изменяет данные в первой (is_delete=1)
Но это вариант — гланды через задницу.
Спасибо, придеться править код (
nekulin написал:
Это глупый вопрос, но все же.
если мы у записи указали is_delete=1 то он не должен ее выдавать в результате при select and update
select . where is_delete=0;
Или, если не хотите переделывать функционал, то можно попробовать через view, но там есть масса ограничений.
Вьюшка не дело.
select . where is_delete=0; Это понятно что через where Я имел виду просто select без явного указания where is_delete=0/ В чем смысл, чтоб не лезсть в код и недополнять условием дополнительным.
Выборка произвольных записей в MySQL
Есть вроде бы обычные задачи, которые можно решить сразу и не задумываясь, но при интенсивном использовании таких решений возникают проблемы, причем не маленькие. Об одной из таких задач я и хочу рассказать.
Проблема
Взяли тут аутсорсера написать небольшой и несложный код на PHP и MySQL. Была одна из задач — выбрать несколько произвольных записей из таблицы в базе MySQL. И что же сделал этот ленивый и глупый аутсорсер? Конечно же написал бред типа такого:
SELECT * FROM tTable ORDER BY RAND ( ) LIMIT 10 ;
На первый взгляд все логично да и работает правильно. Выбираются 10 произвольных записей. Но если взглянуть на план выполнения этого запроса, то станет понятно почему я сложил дюжину матершинных ругательств в адрес глупого аутсорсера.
В процессе выполнения этого запроса MySQL записывает во временную таблицу все (. ) строки исходной таблицы, с одним новым полем, в которое записываются результаты функции RAND () — т.е. набор произвольных значений. Затем эта временная таблица сортируется filesort по добавленному полю с произвольными значениями и далее выбираются первые 10 записей. Полный ппц. А теперь представтье что будет если в исходной таблице 10 000 записей. А что если 1 000 000? А что если эту выборку надо делать раз десять в секунду. Да тут любой супер-пупер сервер надолго уйдет в раздумья.
А ведь если немного проявить смекалку (а аутсорсеры думать не хотят, они работу сдают и идут пропивать деньги), то можно придумать элегантный и быстрый вариант, скорость работы которого не зависит от кол-ва строк в таблице.
Задумка
Итак начнем потихоньку. Сначала упростим задачу, предположим что нам надо выбрать не 10, а всего одну запись.
Тут все довольно просто получается. Нам нужно оперировать только кол-вом записей в таблице, т.к. ключ может быть любым (составным, не числовым), а так же он может быть «разряженным» в результате удаления записей. Для начала узнаем общее кол-во записей в таблице:
SELECT COUNT ( * ) FROM tTable ;
Далее просто вычислим произвольное число от 0 до кол-ва записей в этой таблице
rand_row = round(rand() * row_count);
Теперь без проблем можно сделать выборку произвольной записи:
SELECT * FROM tTable LIMIT rand_row, 1;
Решение на PHP
Так, с упрощенной задачей справились. Теперь нужно одолеть изначально поставленную, т.е. выбрать 10 записей. Логика тут проста: нужно посчитать 10 произвольных чисел от 0 до кол-ва записей в таблице, а затем сделать 10 запросов типа предыдущего и объединить их с помощью UNION.
Есть два варианта как это сделать: можно оформить это в виде куска PHP кода, а можно в виде MySQL хранимой процедуры.
На PHP все очень просто:
$row_count = mysql_result ( mysql_query ( ‘SELECT COUNT(*) FROM tTable;’ ) , 0 ) ;
$query = array ( ) ;
while ( count ( $query ) < 10 ) <
$query [ ] = ‘(SELECT * FROM tTable LIMIT ‘ . rand ( 0 , $row_count ) . ‘, 1)’ ;
>
$query = implode ( ‘ UNION ‘ , $query ) ;
$res = mysql_query ( $query ) ;
Все просто и быстро. На исходной таблице с десятью тысячами записей прирост производительности по сравнению с первоначальным «ленивым» вариантом более чем в 12 раз.
Если записей в исходной таблице не так много и появление повторяющихся строк в выборке неприемлемо — то можно предварительно сформировать список неповторяющихся произвольных значений, а потом уже составить по ним запрос.
Решение на MySQL
Как вариант можно еще сделать это в виде хранимой процедуры:
CREATE PROCEDURE `spRandomSelect` ( IN aSchema VARCHAR ( 50 ) , IN aTable VARCHAR ( 50 ) , IN aNumRows INTEGER ( 11 ) )
NOT DETERMINISTIC
READS SQL DАТА
BEGIN
DECLARE iQuery VARCHAR ( 10000 ) ;
DECLARE iNumRows INTEGER ( 11 ) ;
SET iNumRows = ( SELECT `TABLE _ ROWS` FROM `information _ schema` . `TABLES` t
WHERE t. `TABLE _ SCHEMA` = aSchema AND t. `TABLE _ NAME` = aTable ) ;
SET iQuery = » ;
loop1: LOOP
SET iQuery = CONCAT ( iQuery , ‘(SELECT * FROM `’ , aSchema , ‘`.`’ , aTable ,
‘` LIMIT ‘ , ROUND ( RAND ( UNIX_TIMESTAMP ( ) + aNumRows ) * iNumRows ) , ‘, 1)’ ) ;
IF aNumRows > 1 THEN
SET iQuery = CONCAT ( iQuery , ‘ UNION ‘ ) ;
END IF ;
SET aNumRows = aNumRows — 1 ;
IF aNumRows > 0 THEN
ITERATE loop1 ;
END IF ;
LEAVE loop1 ;
END LOOP loop1 ;
SET @iQuery = iQuery ;
PREPARE iExecStmt FROM @iQuery ;
EXECUTE iExecStmt ;
DRОP PREPARE iExecStmt ;
END ;
Производительность этого решения поменьше чем при подготовке составного запроса в PHP, но смысл в том чтоб показать возможность реализации и на «чистом» SQL.
Как удалить первые 10000 записей в mysql phpmyadmin
А * зачем ? phpclub.ru/mysql/doc/delete.html и вы определитесь все id которые меньше 10к или первые 10к. это разные вещи, особенно если среди id есть пропуски в нумерации. в принципе я оба варианта написал
5 ноя 2016 в 11:21
@Mike, может добавите ответом? Я бы проголосовал за имеющиеся ответы, раз уж вопрос поднят Духом сообщества, но они меня не устраивают.
8 ноя 2019 в 18:37
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Важно понимать, что именно нужно сделать — удалить первые 10000 id или все id, которые меньше 10000.
Для первого варианта необходимо использовать код ниже:
delete from test order by id limit 10000
Для второго — этот:
delete from test where id
Отслеживать
ответ дан 10 июл 2020 в 7:11
Novitskiy Denis Novitskiy Denis
1,532 11 11 серебряных знаков 27 27 бронзовых знаков
Для удаления первых 10тыс записей, выполните запрос вида:
DELETE FROM table WHERE condition LIMIT 10000
Отслеживать
ответ дан 6 ноя 2016 в 10:26
464 2 2 серебряных знака 4 4 бронзовых знака
Это удаление 10000 случайных строк.
6 ноя 2016 в 12:07
delete from [таблица] where [id] in (select [id] from [таблица] order by [id] ASC limit 10000) [id] - Ваше уникальное поле [таблица] - Название таблицы ASC - с начала (id - число)
delete from customers where CustomerID in (select CustomerID from Customers order by CustomerID ASC limit 2)
Удаление помеченных объектов из базы 1C
Причины на удаление объектов могут быть самыми разными - от ошибочного введения, до упразднения из-за неактуальности.
Если удаляется документ - обязательно нужно проверять, точно ли он не нужен, а так же не связаны ли с ним другие документы.
При удалении элементов справочников, нужно понимать: возможно удалить только элементы, которые не участвовали ни в одном документе - иначе это привете к так называемой "битой ссылке" и к ошибкам в учете.
Поэтому, если вы хотите удалить лишнюю неактуальную номенклатуру, то лучше завести для нее папку и обозначить для пользователей, чтобы не использовали в работе.
Для открытия специальной обработки "Удаление помеченных объектов" нужно зайти в раздел администрирование - поддержка и обслуживание. В разных программах 1С могут быть вариации расположения и названия этой обработки. В УНФ, например, сразу в разделе "Администрирование" есть ссылка "Удаление объектов".
Запускаем обработку.
Какие настройки необходимо сделать?
Автоматическое удаление уничтожит записи всех помеченных объектов, если при проверке у них не будет связи с другими объектами базы. Если вы пометили документ на удаление, чтобы "сейчас не мешался", он так же может быть удален.
Выборочное удаление объектов позволяет вручную определить, какие в данный момент объекты будут удаляться.
Если к удалению стоит 1 миллион объектов, то при автоматическом удалении это займет очень большой период времени, а при выборочном режиме можно указать несколько типов объектов и сначала удалить их, а потом повторить до полного удаления всех объектов.
Блокировка работы в базе. Если в базе работают несколько пользователей, а вам нужно бросить все силы на удаление объектов, нужно поставить эту галочку. Пользователи не смогут своими действиями загружать базу, и она будет заниматься только одной задачей - удалением.
По опыту скажем, не самая нужная настройка, поэтому, если не критично, можно удалять медленно и не мешать работе.
Автоматическое удаление по расписанию. Можно задать базе определенный период, в который она будет выполнять удаление в автоматическом режиме (всё, что возможно). Если у вас серверная база - можно ставить задачу на ночь, при файловой необходимо, чтобы база была у кого-нибудь запущена. Так же можно ставить расписание на конец рабочего дня.
Для примера покажем выборочное удаление без блокировки пользователей.
Нажимаем "Далее" - программа начинает анализ базы и ищет все помеченные объекты. Это занимает какое-то время
![]()
Получаем список типов объектов, которые нужно удалить. Если развернуть список, то можно увидеть все объекты выбранного типа.
![]()
Отметим только первые несколько типов и нажимаем "Удалить"
![]()
Обработка показывает процесс удаления.
![]()
В ходе удаления, обработка смотрит связки удаляемых объектов с другими. Если есть связь - эти объекты не удаляться до решения вопроса связи.
![]()
Для того, чтобы разобраться - необходимо перейти в "Места использования объекта". Открываем связанный объект и ищем там ссылку на удаляемый.
На этой картинке видно, что лого как картинка используется в оформлении организации, но если оно помечено на удаление - стоит уточнить - может и не стоит удалять.
![]()
Для примера все-таки удалим.
![]()
Записываем изменения, переходим обратно в обработку удаления и повторяем.
Как видим лого удалилось, так как нет мест его использования.
![]()
Если это элемент справочника, который ссылается на документы, то такой объект удалять нельзя. Его можно оставить помеченным на удаление, но удалить его не получится.
Удаление документов. Тут могут быть связки с другими документами или регистрами сведений.
![]()
Так же изучаем места использования. Видим, что там прямая ссылка на документ
![]()
![]()
Очищаем поле от удаленной накладной, записываем изменения.
Так же обращайте внимание на ссылки внизу документов или на других вкладках.
![]()
Такую ссылку нужно тоже удалить , нажав на крестик.
В обработке повторяем удаление. Готово - документ удален.
![]()
Если у документа ссылка на регистр сведений, то можно зайти в запись этого регистра, "еще - удалить". Запись будет полностью удалена, а объект спокойно удалиться, если это была единственная причина.
