SQL盲查询:将未知日期时间转换为VARCHAR

时间:2017-11-06 19:32:43

标签: c# sql-server excel datetime

我正在开发一个C#项目,该项目中有一个查询许多表并将其作为Excel工作表输出的方法。这样的表格' tablenames存储在一个数组中,因此命令文本是以编程方式构建的,即

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应用程序实例错误说"某些信息导出为文本"。我不介意。但是,我的客户很生气,因为错误对话框没有抓住焦点,让用户不知道它存在于桌面上打开的一堆窗口下面,更不用说等待用户响应用户点击OK了。

经过几次实验,

// CONVERT(varchar, A_DATE_FIELD, 120)

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

你的解决方案是什么?

提前谢谢。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

通过查询信息模式解决了这个问题

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
    }