首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >mysql中order字段的默认值

问mysql中order字段的默认值
EN

Stack Overflow用户
提问于 2014-10-20 13:23:21
回答 4查看 2.2K关注 0票数 7

在给定的表中,我有一个字段(field_order),它将用作定义显示表行的自定义顺序的方法。当插入一个新记录时,我想用该表中的行数加一个行数来设置特定的字段。

因此,如果表有3行,则在插入新表时,field_order的默认值应为4。

设定这一价值的最佳方法是什么?

插入语句中的简单选择计数?

是否有像CURRENT_TIMESTAMP那样的TIMESTAMP数据类型返回该值的常量?

编辑:其原因是为了能够按照特定字段对表进行排序;该字段将由客户端的用户使用jQuery的可排序操作

EN

回答 4

Stack Overflow用户

发布于 2014-10-28 21:59:21

好的,这个问题的解决方案实际上涉及到一些细微差别。继续,决定回答,但也想解决一些细微之处/细节,这些评论还没有解决。

首先,我强烈建议您不要在主键上使用auto_increment,如果没有其他原因,这些自动增量ids很容易被抛出(例如,回滚事务将干扰它们的INCREMENT does not ROLLBACK )。就像@Sebas提到的那样,也会删除)。

第二,你必须考虑你的存储引擎。如果使用MyISAM,您可以非常迅速地获得表的计数(*)(因为MyISAM总是知道每个表中有多少行)。如果您使用的是INNODB,则不是这样的。根据您需要这个表的目的,您可能可以不使用MyISAM。它不是默认的引擎,但是您当然有可能遇到这样一个需求: MyISAM是一个更好的选择。

你应该问自己的第三件事是:“为什么?”你为什么要用这种方式存储数据呢?那到底能给你什么?实际上,您需要SQL中的这些信息吗?在同一个SQL表的同一个表中?

如果“为什么”有一个合理的答案,那么我最不想问的就是“怎么做?”特别是,您将如何处理并发插入?您将如何处理删除或回滚?

考虑到你的要求,做一个桌子上的计数星基本上是必要的.但即便如此,也存在一些细微差别(删除、回滚、并发),还需要做出一些决定(您使用的是哪个存储引擎;您是否可以使用MyISAM,这对于计数星来说更快)。

不过,最重要的是,我会被问到为什么我一开始就需要这个。也许你真的..。但这是一个非常奇怪的要求。

根据您的编辑:

编辑:这背后的原因是为了能够按特定字段对表进行排序;并且该字段将由客户端的用户使用jQuery的可排序操作。

本质上,您要求的是关于表的元数据。我建议将这些元数据存储在单独的表中,或者完全存储在单独的服务中(弹性搜索、Redis等等)。您需要定期更新该单独的表(或键值存储)。如果在SQL中执行此操作,则可以使用触发器。或者使用类似弹性搜索的方法,您可以同时将数据插入SQL和ES中。无论哪种方式,您都需要解决一些棘手的问题(例如,最终的一致性、并发性,以及在MySQL中使用触发器时可能适得其反的所有光荣事情)。

如果是我,我会注意到两件事。第一,即使是谷歌也没有提供一款时时更新的COUNT(*)。“显示大约XYZ中的1-10行。”他们这么做的部分原因是因为他们拥有我想象中的更多的数据,部分是因为计算一个表的精确COUNT(*)并随时保持它的最新信息实际上是不切实际的(而且很快就变得不可行和让人望而却步)。

因此,要么我将完全更改我的需求,并利用我可以快速获得的统计数据(如果您使用MyISAM存储,那么继续使用count( * ).或者我会考虑维护我的表中的计数星号的索引,该索引通过某些进程(cron作业、触发器等)每隔几个小时、每一天更新一次,或者沿着这条线进行定期更新。

在这个问题上.这个问题永远不会有一个标准的答案。无论你如何管理它,都要做一些权衡。它们可能是在一致性、延迟、可伸缩性、精确的和近似的解决方案方面的权衡,以MyISAM作为交换而失去INNODB。但还是会有权衡的。最终,决定取决于你愿意做什么来获得你的需求。

如果是我的话,我可能会满足我的要求。如果我这么做了,我可能会在弹性搜索中索引它,并确保它每隔几个小时就更新一次。这就是你应该做的吗?这要看情况了。它肯定不是一个“正确的答案”,因为它是一个答案(很多),如果我可以忍受我的count(*)有点过时的工作。

你应该用弹性搜索吗?这要看情况了。但你要面对的是你所做的取舍。这不取决于。为了得到你想要的,你需要决定你愿意放弃什么。如果不是关键的话,就灵活处理需求。

票数 5
EN

Stack Overflow用户

发布于 2014-10-28 22:25:10

也许有更好的方法,但我现在所能想到的就是创建第二个表,该表保存所需的值,并使用触发器进行适当的插入/删除:

下面是一个例子:

代码语言:javascript
复制
-- Let's say this is your table
create table tbl_test(
    id int unsigned not null auto_increment primary key,
    text varchar(50)
);

-- Now, here's the table I propose.
-- It will be related to your original table using 'Id'
-- (If you're using InnoDB you can add the appropriate constraint
create table tbl_incremental_values(
    id int unsigned not null primary key,
    incremental_value int unsigned not null default 0
);

-- The triggers that make this work:
delimiter $$
create trigger trig_add_one after insert on tbl_test for each row
begin
    declare n int unsigned default 0;
    set n = (select count(*) from tbl_test);
    insert into tbl_incremental_values
        values (NEW.id, (n));
end $$

-- If you're using InnoDB tables and you've created a constraint that cascades
-- delete operations, skip this trigger
create trigger trig_remove before delete on tbl_test for each row
begin
    delete from tbl_incremental_values where id = OLD.id;
end $$
delimiter ;

现在,让我们来测试一下:

代码语言:javascript
复制
insert into tbl_test(text) values ('a'), ('b');

select a.*, b.incremental_value 
from tbl_test as a inner join tbl_incremental_values as b using (id);
-- Result:
--    id | text | incremental_value
--    ---+------+------------------
--    1  | a    | 1
--    2  | b    | 2

delete from tbl_test where text = 'b';
select a.*, b.incremental_value 
from tbl_test as a inner join tbl_incremental_values as b using (id);
-- Result:
--    id | text | incremental_value
--    ---+------+------------------
--    1  | a    | 1

insert into tbl_test(text) values ('c'), ('d');
select a.*, b.incremental_value 
from tbl_test as a inner join tbl_incremental_values as b using (id);
-- Result:
--    id | text | incremental_value
--    ---+------+------------------
--    1  | a    | 1
--    3  | c    | 2
--    4  | d    | 3

对于小型数据集来说,这很好,但是作为 says in his answer:

为什么?“为什么要以这种方式存储数据?这实际上给了您什么?您实际上需要SQL中的信息吗?在同一个SQL表的同一个表中吗?

如果您所需要的只是输出结果,那么有一种更简单的方法来完成这个工作:用户变量。

现在假设您的桌子是这样的:

代码语言:javascript
复制
create table tbl_test(
    id int unsigned not null auto_increment primary key,
    ts timestamp,
    text varchar(50)
);

insert into tbl_test(text) values('a');
insert into tbl_test(text) values('b');
insert into tbl_test(text) values('c');
insert into tbl_test(text) values('d');
delete from tbl_test where text = 'b';
insert into tbl_test(text) values('e');

ts列将接受插入每一行的日期和时间的值,因此,如果按该列对其进行排序,将得到按插入顺序排列的行。但现在:如何增加“增量价值”?对用户变量使用一个小技巧是有可能的:

代码语言:javascript
复制
select a.*
     , @n := @n + 1 as incremental_value
--     ^^^^^^^^^^^^ This will update the value of @n on each row
from (select @n := 0) as init -- <-- you need to initialize @n to zero
   , tbl_test as a
order by a.ts;
-- Result:
--   id | ts                  | text | incremental_value
--   ---+---------------------+------+----------------------
--   1  | xxxx-xx-xx xx:xx:xx | a    | 1
--   3  | xxxx-xx-xx xx:xx:xx | c    | 2
--   4  | xxxx-xx-xx xx:xx:xx | d    | 3
--   5  | xxxx-xx-xx xx-xx-xx | e    | 4

但现在..。如何处理大数据集,在其中您可能会使用LIMIT?只需将@n初始化为极限的起始值:

代码语言:javascript
复制
-- A dull example:

prepare stmt from 
    "select a.*, @n := @n + 1 as incremental_value
    from (select @n := ?) as init, tbl_test as a
    order by a.ts
    limit ?, ?";
-- The question marks work as "place holders" for values. If you're working
-- directly on MySQL CLI or MySQL workbench, you'll need to create user variables
-- to hold the values you want to use.
set @first_row = 2, @nrows = 2;
execute stmt using @first_row,   @first_row,   @nrows;
--                 ^^^^^^^^^^    ^^^^^^^^^^    ^^^^^^
--                 Initalizes    The "floor"   The number
--                 the @n        of the        of rows
--                 value         LIMIT         you want
--
-- Set @first_row to zero if you want to get the first @nrows rows
--
-- Result:
--   id | ts                  | text | incremental_value
--   ---+---------------------+------+----------------------
--   4  | xxxx-xx-xx xx:xx:xx | d    | 3
--   5  | xxxx-xx-xx xx-xx-xx | e    | 4
deallocate prepare stmt;
票数 3
EN

Stack Overflow用户

发布于 2017-12-04 16:36:39

原来的问题似乎是想要一种简单的方法来在新记录上设置默认的排序顺序。稍后,用户可以调整"order字段“值。似乎删除和回滚与此无关。

这里有一个简单的解决方案。对于排序顺序字段,将默认值设置为0,并使用主键作为辅助排序。只需将查询中的排序顺序更改为DESC。如果希望默认功能是“先显示最新添加的”,请使用:

代码语言:javascript
复制
SELECT * from my_table
WHERE user_id = :uid
ORDER BY field_order, primary_id DESC

如果要“显示最近添加的最新内容”,请使用:

代码语言:javascript
复制
SELECT * from my_table
WHERE user_id = :uid
ORDER BY field_order DESC, primary_id
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26466753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档