我有这个MFC代码从Microsoft Access数据库中提取名称列表:
// Extracts all the brothers from the specified tables into the passed in array
void CPTSDatabase::BuildBrothersArray(CStringArray &rAryStrBrothers)
{
CWaitCursor wait;
CMapStringToString mapStrBrothers;
CStringArray aryStrQueries, aryStrFields;
CString strText, strBrother;
POSITION sPos;
int iTable, iNumTables;
rAryStrBrothers.RemoveAll();
if (m_dbDatabase.IsOpen())
{
strText.Format(_T("SELECT * FROM [Congregation Speakers] ")
_T("WHERE [Congregation]='%s' ORDER BY Speaker"), (LPCTSTR)GetLocalCongregation());
aryStrQueries.Add(_T("SELECT * FROM Brothers WHERE BrotherChairman=-1"));
aryStrQueries.Add(_T("SELECT * FROM Brothers WHERE BrotherReader=-1"));
aryStrQueries.Add(_T("SELECT * FROM Brothers WHERE BrotherConductorWT=-1"));
aryStrQueries.Add(strText);
aryStrFields.Add(_T("BrotherName"));
aryStrFields.Add(_T("BrotherName"));
aryStrFields.Add(_T("BrotherName"));
aryStrFields.Add(_T("Speaker"));
iNumTables = 4;
for (iTable = 0; iTable < iNumTables; iTable++)
{
GetBrotherData(aryStrQueries[iTable], aryStrFields[iTable], mapStrBrothers);
}
sPos = mapStrBrothers.GetStartPosition();
while (sPos != NULL)
{
mapStrBrothers.GetNextAssoc(sPos, strText, strBrother);
rAryStrBrothers.Add(strBrother);
}
}
}
// Extracts all the brothers from the specified table / field
// A map is used so that we end up with a list of unique brothers
void CPTSDatabase::GetBrotherData(CString strSQL, CString strField,
CMapStringToString &rMapBrothers)
{
CRecordset *pRecordset = NULL;
CString strBrother;
if (!m_dbDatabase.IsOpen())
return;
pRecordset = new CRecordset(&m_dbDatabase);
if (pRecordset != NULL)
{
pRecordset->Open(CRecordset::snapshot,(LPCTSTR)strSQL);
while (!pRecordset->IsEOF() )
{
pRecordset->GetFieldValue(strField, strBrother);
rMapBrothers.SetAt(strBrother, strBrother);
pRecordset->MoveNext();
}
pRecordset->Close();
delete pRecordset ;
}
}
// Locates the Congregation that has the "Local" flag set
// The local congregation is the home congregation
CString CPTSDatabase::GetLocalCongregation()
{
CRecordset *pCongs = NULL;
CString strCong, strQuery;
if (m_dbDatabase.IsOpen())
{
pCongs = new CRecordset( &m_dbDatabase );
if (pCongs != NULL)
{
strQuery = _T("SELECT * FROM [Congregations] WHERE [Local] = 1");
pCongs->Open( CRecordset::snapshot, (LPCTSTR)strQuery );
if( pCongs->GetRecordCount() > 0 )
{
pCongs->GetFieldValue(_T("Congregations"), strCong);
}
}
pCongs->Close();
delete pCongs ;
}
return strCong;
}
正如您所看到的,我有几个表,我正在进行搜索并在列表中添加任何唯一的名称。我不想让任何事情过于复杂,但是可以将这个结合起来是一个查询并提取一个CRecordSet
,其中包含一个唯一的名称列表吗?
我做了一些研究后似乎需要一个UNION。所以我需要将这些查询的不同结果合并为一个列:
SELECT Speaker FROM [Congregation Speakers] WHERE [Congregation]='xyz'
SELECT BrotherName FROM Brothers WHERE BrotherChairman=-1")
SELECT BrotherName FROM Brothers WHERE BrotherReader=-1
SELECT BrotherName FROM Brothers WHERE BrotherConductorWT=-1
结果应按A到Z排序。
我做了一些研究后似乎需要一个UNION。所以我需要将这些查询的不同结果合并为一个列:
SELECT Speaker FROM [Congregation Speakers] WHERE [Congregation]='xyz'
SELECT BrotherName FROM Brothers WHERE BrotherChairman=-1")
SELECT BrotherName FROM Brothers WHERE BrotherReader=-1
SELECT BrotherName FROM Brothers WHERE BrotherConductorWT=-1
结果应按A到Z排序。
我试过了:
void CPTSDatabase::BuildBrothersArray(CStringArray &rAryStrBrothers)
{
CWaitCursor wait;
CRecordset *pRecordset = nullptr;
if (!m_dbDatabase.IsOpen())
return;
pRecordset = new CRecordset(&m_dbDatabase);
if (pRecordset != nullptr)
{
CString strSQL = _T(""), strName = _T("");
strSQL.Format(_T("WITH CTE(Name) AS(")
_T("SELECT Speaker FROM [Congregation Speakers] WHERE [Congregation] = '%s' ")
_T("UNION ")
_T("SELECT BrotherName FROM Brothers WHERE BrotherChairman = -1 OR BrotherReader = -1 OR BrotherConductorWT = -1)")
_T(") ")
_T("SELECT Name FROM CTE ORDER BY Name ASC"), (LPCTSTR)GetLocalCongregation());
try
{
pRecordset->Open(CRecordset::snapshot, (LPCTSTR)strSQL);
while (!pRecordset->IsEOF())
{
pRecordset->GetFieldValue(_T("Name"), strName);
rAryStrBrothers.Add(strName);
pRecordset->MoveNext();
}
pRecordset->Close();
}
catch (CDBException* e)
{
TCHAR szError[_MAX_PATH];
e->GetErrorMessage(szError, _MAX_PATH);
AfxMessageBox(szError);
}
delete pRecordset;
}
}
但是我收到了这个错误:
这似乎工作正常:
strSQL.Format(_T("SELECT Speaker AS Name FROM [Congregation Speakers] WHERE [Congregation] = '%s' ")
_T("UNION ")
_T("SELECT BrotherName AS Name FROM Brothers WHERE BrotherChairman = -1 OR BrotherReader = -1 OR BrotherConductorWT = -1 ORDER BY Name ASC"), (LPCTSTR)GetLocalCongregation());
答案 0 :(得分:2)
没有尝试过,只是快速入侵:
WITH CTE(Name) AS (
SELECT Speaker FROM [Congregation Speakers] WHERE [Congregation]='xyz'
UNION
SELECT BrotherName FROM Brothers WHERE BrotherChairman=-1 OR BrotherReader=-1 OR BrotherConductorWT=-1
)
SELECT Name FROM CTE ORDER BY Name ASC
请不要从用户输出中动态编写SQL字符串,而是使用参数化查询,否则您将容易受到SQL注入攻击。
答案 1 :(得分:0)
根据原始答案,这适用于我的CRecordSet
:
strSQL.Format(
_T("SELECT Speaker AS Name FROM [Congregation Speakers] WHERE [Congregation] = '%s' ")
_T("UNION ")
_T("SELECT BrotherName AS Name FROM Brothers WHERE ")
_T("BrotherChairman = -1 OR ")
_T("BrotherReader = -1 OR ")
_T("BrotherConductorWT = -1 OR ")
_T("BrotherHospitality = -1 OR ")
_T("BrotherInterpreter = -1 OR ")
_T("BrotherMiscellaneous = -1 ")
_T("ORDER BY Name ASC"), (LPCTSTR)GetLocalCongregation());