【问题标题】:How to concatenate a datetime field with a string in T-SQL如何在 T-SQL 中将日期时间字段与字符串连接起来
【发布时间】:2020-06-11 19:59:58
【问题描述】:

我有一个动态查询,我正在尝试使用 sp_executesql 执行它。在动态查询中,我有一个日期时间类型的字段。此字段作为参数从 C# .NET 传递到 SQL Server 中的存储过程。我使用典型命令从 C# 调用这个 sp:

    public static object ExecuteProcedure(int userId, DbConnection con, DbTransaction trans, string procedureName, bool withLog, params MyCustomParameter[] parameters)
    {
        if (con.State != ConnectionState.Open)
            con.Open();

        bool bMyTransaction = trans == null;
        if (trans == null)
            trans = con.BeginTransaction();

        try
        {
            MyLog log = withLog ? MyLog.FromProcedure(trans, procedureName, parameters) : null;

            DbCommand command = con.CreateCommand();
            command.CommandType = System.Data.CommandType.StoredProcedure;
            command.CommandText = procedureName;
            command.Transaction = trans;
            command.AddMyCustomParameters(parameters);

            int result = command.ExecuteNonQuery();

            if (log != null)
                log.SaveLogData();

            if (bMyTransaction == true)
                trans.Commit();
            return result;
        }
        catch (Exception ex)
        {
            if (bMyTransaction == true)
                trans.Rollback();
            return null;
        }
    }

它在该行中抛出一个异常:

int result = command.ExecuteNonQuery();

抛出的错误是(从西班牙语翻译):

在日期和/或时间中转换字符串时出错。

存储过程如下:

CREATE PROCEDURE [dbo].[spLogger]   
    @Id varchar(100),
    @Param1 varchar(100),
    @Param2 varchar(15),
    @Param3 int,
    @DateTimeField datetime,
    @Param4 varchar(100),
    @TargetTable tinyint = 0
AS
BEGIN
    DECLARE @sqlCommand nvarchar(max)
    DECLARE @tblName nvarchar(100)  

    SET @tblName = CASE @TargetTable 
                     WHEN 0 THEN '[dbo].[LogTable_01]'
                     WHEN 1 THEN '[dbo].[LogTable_02]'
                     WHEN 2 THEN '[dbo].[LogTable_03]'
                     ELSE ''
                  END

    IF @tblName <> ''
    BEGIN
        SET @sqlCommand =
        'INSERT INTO ' + @tblName +
                   '([Id] ' +
                   ',[Param1] ' +
                   ',[Param2] ' +
                   ',[Param3] ' +
                   ',[MyDateTimeField] ' +
                   ',[Param4]) ' +
             'VALUES' +
                   '(''' + @Id  + ''',''' + @Param1 + ''',''' + @Param2 + ''',' + CAST(@Param3 AS VARCHAR(10)) + ',' + @DateTimeField + ',''' + @Param4 + ''')'

        EXECUTE sp_executesql @sqlCommand
    END    
END

参数@DateTimeField 是从C# 传递的,它是DateTime 类型。该参数传递的值如下:

27/02/2020 18:05:05

在表中,MyDateTimeField 定义为日期时间。

那么如何将 T-SQL 中的日期时间字段连接到字符串?

你也可以看到我连接了一个 INT 类型,参数@Param3,我也想知道我是否也可以连接。

【问题讨论】:

  • 您是否尝试过转换日期时间,然后concat? mssqltips.com/sqlservertip/1145/…
  • 你不要连接它,你应该用sp_executesql传递它们。如果您以正确的方式进行操作,这将不是问题。
  • @iakobski 不,OP 需要参数化
  • @Larnu 感觉有些人看不懂cmets。
  • @Çöđěxěŕ 非常感谢您的想法。我已经按照您所说的做了,并且以同样的方式 Lamu 在下面回答。现在它起作用了!!!!!!!!!!非常感谢!!!!!!!

标签: c# sql-server tsql stored-procedures .net-4.5


【解决方案1】:

不要注入参数;它们是参数。您需要通过将它们作为参数添加到sys.sp_executesql 来对它们进行参数化。那么你就不会有连接datetime 的问题,因为你实际上传递了一个datetime 数据类型:

CREATE PROCEDURE [dbo].[spLogger]   
    @Id varchar(100),
    @Param1 varchar(100),
    @Param2 varchar(15),
    @Param3 int,
    @DateTimeField datetime,
    @Param4 varchar(100),
    @TargetTable tinyint = 0
AS
BEGIN
    DECLARE @sqlCommand nvarchar(max);
    DECLARE @CRLF nchar(2) = NCHAR(13) + NCHAR(10); --This helps with formatting
    DECLARE @tblName sysname; --Changed to proper data type

    SET @tblName = CASE @TargetTable 
                     WHEN 0 THEN N'LogTable_01'
                     WHEN 1 THEN N'LogTable_02'
                     WHEN 2 THEN N'LogTable_03'
                  END;

    IF @tblName IS NOT NULL
    BEGIN
        SET @sqlCommand =N'INSERT INTO dbo.' + QUOTENAME(@tblName) + ' ([Id] ' + @CRLF +
                         N'                                        ,[Param1] ' + @CRLF +
                         N'                                        ,[Param2] ' + @CRLF +
                         N'                                        ,[Param3] ' + @CRLF +
                         N'                                        ,[MyDateTimeField] ' + @CRLF +
                         N'                                        ,[Param4]) ' + @CRLF +
                         N'VALUES (@Id, @Param1, @Param2, @Param3, @DateTimeField, @Param4);'l

        --PRINT @SQL; --your debugging friend.
        EXECUTE sys.sp_executesql @sqlCommand, N'@Id varchar(100),@Param1 varchar(100),@Param2 varchar(15),@Param3 int,@DateTimeField datetime,@Param4 varchar(100)',@Id, @Param1, @Param2, @Param3, @DateTimeField, @Param4;

    END;
END;

【讨论】:

  • QUOTENAME 这背后的原因是什么,TBH,我以前从未见过这样做。
  • Why QUOTENAME is important@Çöđěxěŕ。 TL;DR 它确保对象名称的安全注入。很惊讶你没有看到我的另一个使用它的答案。 :)
  • 读起来很有趣,很有意义。感谢您的反馈,是的,我很惊讶我还没有看到这个;第一次。
  • 谢谢。我倾向于将任何需要注入的对象包装在QUOTENAME 中,无论它是否来自“安全”来源。它只是将来证明任何代码应该(何时)移动目标职位,并且如果您的对象名称包含](因为人们很愚蠢,请创建它们>_
  • 感谢 Lamu 提供了一个很好的例子。你拯救了我的一天;)它就像一个魅力!还有关于 QUOTENAME 的有趣文章。我不知道。太好了!
【解决方案2】:
select a.a, FORMAT(a.a,'dd/MM/yyyy h:mm:ss tt') 
from
 (select convert(datetime, '2020-02-27 12:30:00' ) as a) a

输出:

2020-02-27 12:30:00.000 27/02/2020 12:30:00 PM

这显示了如何将datetime 转换为字符串,您可以使用该字符串连接到您的@sqlCommand。

【讨论】:

  • 这不是一个答案,它是,但不是 OP 需要的,并且没有帮助恕我直言。
  • @Çöđěxěŕ:我试图回答:“那么如何将 T-SQL 中的日期时间字段连接到字符串?”
  • 然后解释一下,这是如何连接 DateTime 到/在字符串中的;它是动态的。
  • 它不是动态的,是一个名为@DateTimeField的输入参数,相当固定....
猜你喜欢
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
相关资源
最近更新 更多