【问题标题】:MySQL: Add sequence column based on another fieldMySQL:基于另一个字段添加序列列
【发布时间】:2021-04-15 22:13:28
【问题描述】:

我正在处理一些遗留代码/数据库,并且需要向数据库中添加一个字段,该字段将记录与该(外国)ID 相关的序列号。

示例表数据(当前):

ID     ACCOUNT     some_other_stuff
1      1           ...
2      1           ...
3      1           ...
4      2           ...
5      2           ...
6      1           ...

我需要添加一个 sequenceid 列,为每个帐户分别递增,实现:

ID     ACCOUNT     SEQ     some_other_stuff
1      1           1       ...
2      1           2       ...
3      1           3       ...
4      2           1       ...
5      2           2       ...
6      1           4       ...

请注意,顺序与帐户有关。

有没有办法可以在 SQL 中实现这一点,或者我是否可以使用 PHP 脚本来为我完成这项工作?

TIA, 凯夫

【问题讨论】:

    标签: php mysql sequence


    【解决方案1】:

    问题被标记为“mysql”,所以是的,MySQL 的 auto_increment 可以创建 groupwise 顺序 id。
    http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html:

    对于 MyISAMBDB 表,您可以在多列索引的辅助列上指定 AUTO_INCREMENT。在这种情况下,AUTO_INCREMENT 列的生成值计算为MAX(auto_increment_column) + 1 WHERE prefix=given-prefix。当您要将数据放入有序组时,这很有用。

    编辑:示例 php 脚本(使用 PDO,但它与 php-mysql 模块是同一个游戏)

    $pdo = new PDO('mysql:host=...;dbname=...', '...', '...'); 
    $pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    
    // example table
    $pdo->exec(
      'CREATE TEMPORARY TABLE Foo (
        id int auto_increment,
        account int,
        someotherstuff varchar(32),
        primary key(account,id)
      ) engine=MyIsam'
    );
    // insert example data
    $stmt = $pdo->prepare('INSERT INTO Foo (account,someotherstuff) VALUES (?,?)');
    $stmt->execute(array(1, '1a'));
    $stmt->execute(array(1, '1b'));
    $stmt->execute(array(1, '1c'));
    $stmt->execute(array(2, '2a'));
    $stmt->execute(array(2, '2b'));
    $stmt->execute(array(1, '1d'));
    unset($stmt);
    
    // query data
    foreach( $pdo->query('SELECT account,id,someotherstuff FROM Foo') as $row ) {
      echo $row['account'], ' ', $row['id'], ' ', $row['someotherstuff'], "\n";
    }
    

    打印

    1 1 1a
    1 2 1b
    1 3 1c
    2 1 2a
    2 2 2b
    1 4 1d
    

    【讨论】:

    • 感谢您的回复。抱歉 - 我应该指定表是 innoDB。我最终选择了下面的临时表解决方案,但感谢您的输入!干杯!
    • 不错的解决方案。这是正确的答案。效果很好。
    【解决方案2】:

    创建触发器:

    CREATE TRIGGER trg_mytable_bi
    BEFORE INSERT ON mytable
    FOR EACH ROW
    BEGIN
          DECLARE nseq INT;
          SELECT  COALESCE(MAX(seq), 0) + 1
          INTO    nseq
          FROM    mytable
          WHERE   account = NEW.account;
          SET NEW.seq = nseq;
    END;
    

    【讨论】:

    • 感谢您的回复,但最后我还是选择了上面的临时表解决方案。
    • 对于任何有混淆错误问题的人,请参阅此处关于在触发器中使用分隔符:stackoverflow.com/questions/5814153/…
    【解决方案3】:

    这应该可以,但可能很慢:

    CREATE temporary table seq ( id int, seq int);
    INSERT INTO seq ( id, seq )
        SELECT id, 
          (SELECT count(*) + 1 FROM test c 
          WHERE c.id < test.id AND c.account = test.account) as seq 
        FROM test;
    
    UPDATE test INNER join seq ON test.id = seq.id SET test.seq = seq.seq;
    

    我称该表为“测试”;显然需要正确设置。您必须使用临时表,因为 MySQL 不允许您使用正在更新的同一个表中的子选择。

    【讨论】:

      猜你喜欢
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多