【问题标题】:How to convert parameters substring to the column type in C#?如何将参数子字符串转换为 C# 中的列类型?
【发布时间】:2018-09-18 13:33:01
【问题描述】:

我有一个 INSERT 和一个 VARCHAR 参数。 SQL 如下所示:

INSERT INTO FLAGS (TIME_STAMP, FLAG) 
SELECT SUBSTRING(@s1 FROM 1 FOR 23), SUBSTRING(@s1 FROM 24 FOR 2) 
FROM RDB$DATABASE;

发送方式如下:

using (FbConnection connection = new FbConnection(ConnectionString))
{
    try
    {
        connection.Open();
        var transaction = connection.BeginTransaction();
        var command = new FbCommand(sqlCommand, connection, transaction);
        command.Parameters.Add("@s1", "2018-09-12 08:37:51.00083");
        command.ExecuteNonQuery();
        transaction.Commit();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

TIME_STAMP 列是TIMESTAMPFLAG 列是INTEGER。在实际应用程序中,INSERT 中会有几行,而不仅仅是一行。还会有更多列,因此我希望将一行的参数数量保持在尽可能低的水平。
如果我运行这段代码,它会给我:
Exception thrown: 'System.FormatException' in FirebirdSql.Data.FirebirdClient.dll

如果我像这样更改命令:

INSERT INTO FLAGS (TIME_STAMP, FLAG) 
SELECT SUBSTRING(@s1 FROM 1 FOR 23), CAST(SUBSTRING(@s1 FROM 24 FOR 2) AS INTEGER) 
FROM RDB$DATABASE;

它给了我这个错误:

Exception thrown: 'FirebirdSql.Data.FirebirdClient.FbException' in 
FirebirdSql.Data.FirebirdClient.dll
Dynamic SQL Error
SQL error code = -804
Data type unknown

FWIR 这应该是可能的。至少这在 FlameRobin 中有效(CAST 的版本也有效):

SET TERM ^ ; 
EXECUTE BLOCK AS 
DECLARE s1 VARCHAR(25) = '2018-09-12 08:37:51.00083'; 
BEGIN 
INSERT INTO FLAGS (TIME_STAMP, FLAG) 
SELECT SUBSTRING(:s1 FROM 1 FOR 23), SUBSTRING(:s1 FROM 24 FOR 2) 
FROM RDB$DATABASE;
END^ 
SET TERM ; ^

有人能指出正确的方向吗?

编辑
结果应该是:

TIME_STAMP              | FLAG
------------------------+-----
2018-09-12 08:37:51.000 | 83

【问题讨论】:

  • 我建议考虑类似stackoverflow.com/questions/17882366/… 并单独指定每个参数。
  • 其实我在EXECUTE BLOCK中有多次插入,但是在速度和内存消耗方面存在问题,所以我正在寻找其他一些可能更有效的解决方案。
  • “也会有更多的列,所以我想将一行的参数数量保持在尽可能低的水平”——一个非常奇怪的想法。为了模糊启发式和没有保证,您想删除类型安全和确定性行为。出于晦涩的原因,您想将自己射入脚中。好吧,你刚刚做到了。
  • @Arioch'当 OP 使用 FirebirdSql.Data.FirebirdClient 时,链接到 IBProvider 文档不正确,并且该驱动程序确实支持在参数名称中使用 @(如 System.Data. SqlClient for SQL Server)
  • @Arioch'The 这不是我的意思。您根据其他驱动程序的文档提出了不正确的声明。

标签: c# casting substring firebird firebird2.5


【解决方案1】:

在大多数情况下,Firebird 无法推断选择列表中参数的数据类型(有例外,但这不是其中之一)。您将需要显式转换它以定义数据类型和长度。请注意,这只适用于 Firebird 2.5 或更高版本。

你需要使用:

INSERT INTO FLAGS (TIME_STAMP, FLAG) 
SELECT SUBSTRING(cast(@s1 as varchar(25)) FROM 1 FOR 23), CAST(SUBSTRING(cast(@s1 as varchar(25)) FROM 24 FOR 2) AS INTEGER) 
FROM RDB$DATABASE

然而,做这个客户端并使用适当类型的普通insert into .. values (..,..) 比使用字符串类型的东西要好得多。

它在execute block 中起作用的原因是因为您已经将s1 定义为varchar(25)

【讨论】:

  • 它有效,谢谢。我想尝试这种方法,因为我正在尝试减少内存消耗(并提高速度)以定期插入多行(每次大约 400k),并且根据this article 这个解决方案可以帮助我。
  • 我也尝试了推荐的方式(EXECUTE BLOCK 中的INSERT INTO 和参数集),但它给了我-901 未定义的消息编号——即使只有一行如果我删除@ 987654329@ 从开头和END 从结尾。
  • @Artholl 这完全取决于您如何使用执行块;参数需要正确传递给执行块。真的,不要依赖为不同数据库系统编写的文章,并假设它会直接转换到另一个数据库系统。
  • 我只是想测试一下该解决方案是否在 Firebird 中也给了我一些改进,我绝对不依赖它。到目前为止,我似乎不会使用它。但多亏了你,我学到了一些关于 Firebird 的知识,这在未来可能会对我有所帮助,所以这并不是完全浪费时间 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 2020-11-22
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
相关资源
最近更新 更多