为多行查询选择列

时间:2016-06-20 03:22:22

标签: c# sql

目前我正试图在c#中查询损坏的数据库。最近引入的错误是,当以特定方式输入数据时,列中的值默认为0,这对我来说是有问题的,因为我无法控制用户做什么或做什么dba。

为了解决这个问题,我找到了输出给用户的数据的另一条路径。问题是,如果列出现非零数字,我的主管要求支持旧方法。

我试图用case或if命令来做这个,但是我对sql不是那么好,所以我不是100%确定我哪里出错了或者如何正确/有效地去做。这些是当前状态下的命令:

SqlCommand caseCmd = new SqlCommand(
  "SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TERMCODE =" +
    " CASE H.ITEMCODE WHEN 0" +
    " THEN TN.TERMID" +
    " ELSE H.ITEMCODE END" +
  " FROM " + _databaseName + ".dbo.PASTHISTORY H" +
    " INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
    " INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TERMCODE" +
    " INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TERMCODE" +
  " WHERE H.INTERNALID = @patientid" +
    " AND H.RECORDSTATUS = 1" +
    " AND ((H.CREATED >= @mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= @mindate)))" +
    " AND TC.RECORDSTATUS = 1",
  Connection);
caseCmd.Parameters.AddWithValue("@patientid", int.Parse(patientId));
caseCmd.Parameters.AddWithValue("@mindate", minEnteredDate);
// Current error:
//   When using 'TC.TERMID = TERMCODE', I get the error 'The conversion of the varchar value 
//   "3951000119103  " overflowed an int column'.
//   This is alleviated by using either TN.TERMID OR H.ITEMCODE

SqlCommand ifCmd = new SqlCommand(
  "IF (H.ITEMCODE = 0)" +
    " SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TN.TERMID" +
    " FROM " + _databaseName + ".dbo.PASTHISTORY H" +
      " INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
      " INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TN.TERMID" +
      " INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TN.TERMID" +
    " WHERE H.INTERNALID = @patientid" +
      " AND H.RECORDSTATUS = 1" +
      " AND ((H.CREATED >= @mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= @mindate)))" +
      " AND TC.RECORDSTATUS = 1" +
  " ELSE IF (H.ITEMCODE <> 0)" +
    " SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE, TC.DOCLE, TC.ICPC, TC.ICD10" + 
    " FROM " + _databaseName + ".dbo.PASTHISTORY H" +
      " INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = H.ITEMCODE" +
      " INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = H.ITEMCODE" +
    " WHERE H.INTERNALID = @patientid" +
      " AND H.RECORDSTATUS = 1" +
      " AND ((H.CREATED >= @mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= @mindate)))" +
      " AND TC.RECORDSTATUS = 1", 
  Connection);
ifCmd.Parameters.AddWithValue("@patientid", int.Parse(patientId));
ifCmd.Parameters.AddWithValue("@mindate", minEnteredDate);
// Current error:
//   Getting two lines both saying 'The multi-part identifier "H.ITEMCODE" could not be bound.'
//   I trust this is because of the IF and ELSE IF statements.
//   Starting to think IF isn't the answer for me.

// Use either
SqlDataReader rdr = caseCmd.ExecuteReader();
// or
// SqlDataReader rdr = ifCmd.ExecuteReader();

这是否可以远程实现,或者我应该考虑为两种备选方案制作两个sql命令并搜索它们两者?

1 个答案:

答案 0 :(得分:0)

为了清楚起见,我从C#字符串中取出了SQL并使用了CTE。基本上,您可以先修补数据,然后将其用于查找:

(-1)

这种情况看起来也很可疑:

WITH PatchedHistory AS (
    SELECT 
        H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT
        , COALESCE(TN.TERMID, H.ITEMCODE) AS ITEMCODE --< TERMID with ITEMCODE fall-back
    FROM _databaseName.dbo.PASTHISTORY H
    LEFT JOIN _drugDatabaseName.dbo.TERMNAMES TN
        ON H.ITEMCODE = 0                             --< Lookup only if ITEMCODE is 0
        AND TN.TERMNAME = H.ITEMTEXT
    WHERE H.INTERNALID = @patientid                   --< Apply most of the filtering here
        AND H.RECORDSTATUS = 1
        AND ((H.CREATED >= @mindate)                  --< Suspicious condition
         OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= @mindate))
        )
)
SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE
    , TC.DOCLE, TC.ICPC, TC.ICD10                     --< Add the rest of the data
FROM PatchedHistory H
    INNER JOIN _drugDatabaseName.dbo.TERMCODES TC
        ON TC.TERMID = H.ITEMCODE                     --< Join on the "patched" ITEMCODE
    INNER JOIN _drugDatabaseName.dbo.CONDITIONS C
        ON C.TERMID = H.ITEMCODE                      --< Join on the "patched" ITEMCODE
WHERE TC.RECORDSTATUS = 1

技术上它等同于

        AND ((H.CREATED >= @mindate)
         OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= @mindate))
        )

看起来意图是

        AND ((H.CREATED >= @mindate) OR (H.UPDATED >= @mindate))