【问题标题】:Pass SELECT MAX(`Id`) FROM Table to setval()将 SELECT MAX(`Id`) FROM Table 传递给 setval()
【发布时间】:2019-11-29 04:21:41
【问题描述】:

我想将 (SELECT MAX(Id) FROM Table 传递给我尝试过的 mariadb 的 setval() 函数:

SELECT setval(`MySequence`, (SELECT MAX(`Id`) FROM `Table`));

但是不行,我也试过了:

SET @max_value = (SELECT MAX(`Id`) FROM `Table`);
SELECT setval(`MySequence`, @max_value);

我该怎么做?

编辑我在发布问题时犯了一个错误。我在第二个代码上使用了 SET 并且没有工作

编辑 正如我在 cmets 上所说,我只尝试执行一次,从 Entity Framework Core 迁移执行。我最后做的是执行SELECT MAX(Id) FROM Table 并从迁移代码中恢复该值,以便稍后在$"SELECT setval('sequence', {value}, true)" 上插入它

【问题讨论】:

  • 小心! -- 如果另一个线程潜入,它可以得到你认为你得到的Max(Id)。不要这样做序列!见AUTO_INCREMENT
  • 谢谢,这是一次迁移。它将执行一次,在表上的大型升级将起作用之后。

标签: sql entity-framework-core mariadb sequence-sql mariadb-10.3


【解决方案1】:

我找到了使用prepared statement的解决方法:

SET @max_value = (SELECT MAX(`Id`) FROM `Table`);
EXECUTE IMMEDIATE CONCAT('SELECT SETVAL(`MySequence`, ', @max_value, ')');

【讨论】:

  • 我不再从事这个项目了,这个问题是从 2 年前开始的,但是,这确实有效。 dbfiddle.uk/… 我将您的答案标记为已接受。谢谢。
【解决方案2】:

MariaDB 10.3.16

起似乎不可能做到这一点

我在 https://jira.mariadb.org/browse/MDEV-20111 上提出了一个错误,供开发人员考虑添加此功能或升级文档以明确表示无法完成。

我通过在 c# 代码中使用 Mysqlconnector 选择值来解决这个问题

private long ReadMaxIdFromTable()
{

    MySqlConnection connection = null;
    try
    {
        var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");



        var builder = new ConfigurationBuilder();
        var builderenv = builder.AddJsonFile("config/appsettings.json", optional: false, reloadOnChange: false)
                         .AddJsonFile($"config/appsettings.{environment}.json", false, false).AddEnvironmentVariables();

        IConfigurationRoot configuration = builderenv.Build();
        var connectionString = configuration.GetConnectionString("ConnectionStringName");

        connection = new MySqlConnection(connectionString);
        connection.Open();
        var cmd = connection.CreateCommand() as MySqlCommand;
        cmd.CommandText = @"SELECT MAX(`Id`) FROM `Table`";
        var result = (long)cmd.ExecuteScalar();
        return result;
    }
    catch (Exception)
    {
        throw;
    }
    finally
    {
        if (connection != null && connection.State != System.Data.ConnectionState.Closed)
        {
            connection.Close();
        }
    }
}

没有我想要的那么干净,但它可以完成工作。

稍后我使用SETVAL再次从c#代码中插入sql字符串中的值。

 var currentSeq = ReadMaxIdFromTable();
 migrationBuilder.Sql($"SELECT SETVAL(`MySequence`, {currentSeq}, true);");

另外,请注意所有Up() 代码在任何东西进入数据库之前执行,这意味着SELECT MAX(Id) FROM Table; 必须在迁移开始操作数据库之前产生我们正在寻找的值。

【讨论】:

    【解决方案3】:

    select 中,使用:= 分配变量:

    SELECT @max_value := MAX(`Id`) FROM `Table`;
    SELECT setval(`MySequence`, @max_value);
    

    您可能希望将值加 1。

    我认为你可以做到:

    SELECT setval(`MySequence`, MAX(Id))
    FROM `Table`;
    

    【讨论】:

    • 我将尝试第二个选项并让您知道。我正在使用 SET 但我发布错了
    • 另外,我将 true 作为第三个参数附加到 setval(),所以它知道它必须给出下一个值。
    • 我测试了它,但它也不起作用 :( 您的 SQL 语法有错误;请查看与您的 MariaDB 服务器版本相对应的手册,以获取在 'MAX( 附近使用的正确语法Id)) FROM table'
    • @PabloRecalde 。 . .它适用于 dbfiddle:dbfiddle.uk/….
    • 恐怕不行dbfiddle.uk/…
    【解决方案4】:

    独立语句(不是查询)中,SET通常用于为用户定义的变量赋值。请尝试以下方法:

    SET @max_value = (SELECT MAX(`Id`) FROM `Table`);
    SELECT setval(`MySequence`, @max_value);
    

    【讨论】:

    • 是的,我急着发帖,拼错了 SET。它也不起作用。
    • @PabloRecalde 似乎 setval() 函数仅适用于整数文字,而不适用于表达式/变量。参考:mariadb.com/kb/en/library/setval
    • 我去过那里,但没有明确说明您是否可以使用它们。
    • 甚至 CRATE 或 ALTER 序列文档都没有说您可以或不能使用内部查询/变量,但实际上您似乎不能。
    猜你喜欢
    • 2017-09-27
    • 2011-04-06
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2016-01-19
    相关资源
    最近更新 更多