MYSQL删除查询之谜

时间:2017-10-23 15:37:14

标签: mysql sql

我有2张桌子;一个名为devices,一个名为permanent_users

我正在尝试删除5分钟前创建的设备以及" REALM" (取自永久用户 - 内部联接)等于" MYREALM"。

以下查询不会删除任何内容,直到5分钟前创建的(至少一个)设备属于领域MYREALM ...但它会从设备表中删除所有记录!

我错误地丢失了超过6K的设备。以下是我的DELETE声明 -  我在这做错了什么?

delete devices from devices
inner join (SELECT
  permanent_users.realm,
  devices.name,
  devices.created,
  TimeDiff(Now(), devices.created) AS TimeDifference
FROM
  permanent_users
  INNER JOIN devices ON devices.permanent_user_id = permanent_users.id
WHERE
  (TimeDiff(Now(), devices.created)> '00:05' )AND
  (permanent_users.realm = 'WAVELOC')) myquery;

下面是表格结构:

CREATE TABLE `permanent_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(50) NOT NULL,
  `token` char(36) DEFAULT NULL,
  `name` varchar(50) NOT NULL,
  `surname` varchar(50) NOT NULL,
  `address` varchar(255) NOT NULL,
  `phone` varchar(50) NOT NULL,
  `email` varchar(100) NOT NULL,
  `auth_type` varchar(128) NOT NULL DEFAULT 'sql',
  `active` tinyint(1) NOT NULL DEFAULT '0',
  `last_accept_time` datetime DEFAULT NULL,
  `last_reject_time` datetime DEFAULT NULL,
  `last_accept_nas` varchar(128) DEFAULT NULL,
  `last_reject_nas` varchar(128) DEFAULT NULL,
  `last_reject_message` varchar(255) DEFAULT NULL,
  `perc_time_used` int(6) DEFAULT NULL,
  `perc_data_used` int(6) DEFAULT NULL,
  `data_used` bigint(20) DEFAULT NULL,
  `data_cap` bigint(20) DEFAULT NULL,
  `time_used` int(12) DEFAULT NULL,
  `time_cap` int(12) DEFAULT NULL,
  `time_cap_type` enum('hard','soft') DEFAULT 'soft',
  `data_cap_type` enum('hard','soft') DEFAULT 'soft',
  `realm` varchar(50) NOT NULL DEFAULT '',
  `realm_id` int(11) DEFAULT NULL,
  `profile` varchar(50) NOT NULL DEFAULT '',
  `profile_id` int(11) DEFAULT NULL,
  `from_date` datetime DEFAULT NULL,
  `to_date` datetime DEFAULT NULL,
  `track_auth` tinyint(1) NOT NULL DEFAULT '0',
  `track_acct` tinyint(1) NOT NULL DEFAULT '1',
  `static_ip` varchar(50) NOT NULL DEFAULT '',
  `extra_name` varchar(100) NOT NULL DEFAULT '',
  `extra_value` varchar(100) NOT NULL DEFAULT '',
  `country_id` int(11) DEFAULT NULL,
  `language_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7231 DEFAULT CHARSET=utf8;


CREATE TABLE `devices` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `description` varchar(255) NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '0',
  `last_accept_time` datetime DEFAULT NULL,
  `last_reject_time` datetime DEFAULT NULL,
  `last_accept_nas` varchar(128) DEFAULT NULL,
  `last_reject_nas` varchar(128) DEFAULT NULL,
  `last_reject_message` varchar(255) DEFAULT NULL,
  `permanent_user_id` int(11) DEFAULT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  `perc_time_used` int(6) DEFAULT NULL,
  `perc_data_used` int(6) DEFAULT NULL,
  `data_used` bigint(20) DEFAULT NULL,
  `data_cap` bigint(20) DEFAULT NULL,
  `time_used` int(12) DEFAULT NULL,
  `time_cap` int(12) DEFAULT NULL,
  `time_cap_type` enum('hard','soft') DEFAULT 'soft',
  `data_cap_type` enum('hard','soft') DEFAULT 'soft',
  `realm` varchar(100) NOT NULL DEFAULT '',
  `realm_id` int(11) DEFAULT NULL,
  `profile` varchar(100) NOT NULL DEFAULT '',
  `profile_id` int(11) DEFAULT NULL,
  `from_date` datetime DEFAULT NULL,
  `to_date` datetime DEFAULT NULL,
  `callingstationid` varchar(50) DEFAULT NULL,
  `acctstarttime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2941 DEFAULT CHARSET=utf8;

我遇到了各种错误,提出了你的建议!我的sql版本是: root @ vmi83670:〜#mysql -V mysql Ver 14.14 Distrib 5.5.53,debian-linux-gnu(x86_64)使用readline 6.3

对于rudamental方法感到抱歉,但我不知道如何以更好的方式显示myt数据。

The "permanent_users" table

The "devices" table

所以...删除超过5分钟的设备并且是关系的一部分" WAVELOC" ...

3 个答案:

答案 0 :(得分:1)

您错过了WHERE语句的DELETE条款。如果你告诉DBMS删除表中的记录,但是不指定哪些记录,它将删除所有记录。

  

注意:删除表格中的记录时要小心!注意WHERE   DELETE语句中的子句。 WHERE子句指定哪个   应删除的记录。如果省略WHERE子句,则全部   表中的记录将被删除!

https://www.w3schools.com/sql/sql_delete.asp

作为旁注,如果您是DBA,则应复制数据库以使用开发环境,这样您就可以测试代码,而不必担心会破坏生产数据。

答案 1 :(得分:1)

所以你想:

Delete d
  from devices d
  join permanent_users pu
    on pu.id = d.permanent_user_id
   and pu.realm_id = d.realm_id
   and pu.realm = d.realm
   and pu.realm = 'WAVELOC'
 where now() - d.created > 300;

这是对的吗?

或者这是正确的吗?

Delete d
  from devices d
  join permanent_users pu
    on pu.id = d.permanent_user_id
   and pu.realm = 'WAVELOC'
 where now() - d.created > 300;

不清楚realm中的realm_iddevices是否应与permanent_users中的@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.main_menu, menu); MenuItem mSearchMenuItem = menu.findItem(R.id.search); SearchView searchView = (SearchView) mSearchMenuItem.getActionView(); search(searchView); } public static void search(android.support.v7.widget.SearchView searchView) { searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { mCategoryAdapter.getFilter().filter(newText); return true; } }); } 相关联。

MySQL中的日期算术返回两个日期时间列之间的秒数。 300秒相当于5分钟。

答案 2 :(得分:-1)

不确定您是否显示表定义,我认为那里存在一些毛刺或语法错误,但我宁愿将查询结构如下:

从设备d中删除d.id in(在这里使内部联接只返回你想要的设备的id)。

此外,在内部联接中,您应该只获取要在表之间匹配的字段,并将其余的参数用于where部分。

它应该是这样的:

delete from devices d where d.id in (

SELECT q.permanent_user_id

FROM
  permanent_users p
  INNER JOIN devices q ON q.permanent_user_id = p.id
WHERE
  (TimeDiff(Now(), q.created)> '00:05' )AND
  (p.realm = 'WAVELOC')
)
);

在执行删除之前尝试内部选择,这应该是正常操作,以避免在查询格式错误的情况下丢失数据。