【问题标题】:SQL Blind Query: Convert Unknown DateTime into VARCHARSQL盲查询:将未知日期时间转换为VARCHAR
【发布时间】:2017-11-06 19:32:42
【问题描述】:

我正在处理一个 C# 项目,该项目中有一个方法可以查询许多表并将它们输出为 Excel 工作表。这些表的表名存储在一个数组中,因此命令文本是通过编程方式构建的,即,

string query = string.empty;

foreach (string tbl in tables) {

    query = $"SELECT * FROM {tbl} WHERE DATEFROM BETWEEN @from AND @to"; // DATEFROM field is guaranteed to exist

    // run the SQLCommand here
    // e.g. I fill a ds (as DataSet object) with the query result

}

这段代码没有错误,但是一旦我使用非常方便的方式将 DataTable/Dataset 导出到 Excel

xmlMap = myWorkbook.XmlMaps.Add(ds.GetXmlSchema(), "Export");
myWorkbook.XmlImportXml(ds.GetXml(), out xmlMap, true, xlWsht.Range["A1"]);

。 . .我有时会收到一个 Excel 应用程序实例错误,提示“某些信息已导出为文本”。我不介意。然而,我的客户很生气,因为那个错误对话框没有抓住焦点,并且让用户没有意识到它在他们桌面上打开的一堆窗口下面的存在,更不用说它正在等待用户点击确定的用户响应。

经过几次实验,

// CONVERT(varchar, A_DATE_FIELD, 120)

解决了问题(避免再次弹出此错误消息)。但是,由于表的数量和每个表中的许多不同的日期时间字段,硬编码所有 SELECT CONVERT(varchar, A_DATE_FIELD, 120) 查询是不切实际的(至少在我的情况下)。

您对此有何解决方案?

提前谢谢你。

【问题讨论】:

    标签: c# sql-server excel datetime


    【解决方案1】:

    如何查询给定表中的所有列并从中构建查询,而不是“SELECT *”?抱歉,我对 SQL Server 不是很熟悉,但在 Oracle 中,您可以查询 dba_tab_cols 以获取表的所有列以及每列的数据类型。在构建查询字符串时,如果列是 DATE,则将转换构建到您的 SELECT 中。

    【讨论】:

      【解决方案2】:

      通过查询 INFORMATION SCHEMA 解决了这个问题

      public static string GenerateSafeSelectAllQueryString(string tableName, SQLDateConversionStyle dateConvertType) {
      
              var retval = new StringBuilder();
      
              using (SqlConnection con = new SqlConnection(PSQLServerUtilities.ConnectionStringStatic)) {
      
                  string query = "SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=@tableName ORDER BY ORDINAL_POSITION ASC;";
      
                  try {
      
                      con.Open();
      
                      using (SqlCommand com = new SqlCommand(query, con)) {
      
                          com.Parameters.AddWithValue("tableName", tableName);
      
                          using (SqlDataReader reader = com.ExecuteReader()) {
      
                              if (reader.HasRows) {
      
                                  using (DataTable dt = new DataTable(tableName)) {
      
                                      dt.Load(reader);
      
                                      foreach (DataRow row in dt.Rows) {
                                          retval.Append((row[1].ToString() == "datetime") ?
                                              $"CONVERT(varchar, {row[0].ToString()}, {(int)dateConvertType}) AS '{row[0].ToString()}', " : $"{row[0].ToString()}, ");
                                      }
      
                                      retval.Length -= 2;
      
                                  }
      
                              }
      
                          }
      
                      }
      
                  } catch (Exception ex) {
                      throw ex;
                  } finally {
                      con.Close();
                      GC.Collect();
                      GC.WaitForPendingFinalizers();
                  }
      
              }
      
              return retval.ToString();
          }
      
      
          /// <summary>
          /// Different types of converting SQL DateTime to varchar
          /// Source: https://www.w3schools.com/sql/func_sqlserver_convert.asp
          /// </summary>
          public enum SQLDateConversionStyle {
              /// <summary>
              /// Format: mon dd yyyy hh:miAM/PM
              /// </summary>
              Default = 100,
              /// <summary>
              /// Format: mm/dd/yyyy
              /// </summary>
              US = 101,
              /// <summary>
              /// Format: hh:mm:ss
              /// </summary>
              HoursOnly = 108,
              /// <summary>
              /// Format: yyyy/mm/dd
              /// </summary>
              Japan = 111,
              /// <summary>
              /// Format: yyyy-mm-dd hh:mi:ss
              /// </summary>
              ODBCCanonical = 120,
              /// <summary>
              /// Format: yyyy-mm-dd hh:mi:ss.mmm
              /// </summary>
              ODBCCanonicalMillis,
              /// <summary>
              /// Format: yyyy-mm-ddThh:mi:ss.mmmZ
              /// </summary>
              ISO8601 = 127
          }
      

      【讨论】:

        猜你喜欢
        • 2019-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-15
        • 1970-01-01
        • 2014-06-07
        相关资源
        最近更新 更多