/**************************************************************************** ** (c) Copyright IBM Corp. 2007 All rights reserved. ** ** The following sample of source code ("Sample") is owned by International ** Business Machines Corporation or one of its subsidiaries ("IBM") and is ** copyrighted and licensed, not sold. You may use, copy, modify, and ** distribute the Sample in any form without payment to IBM, for the purpose of ** assisting you in the development of your applications. ** ** The Sample code is provided to you on an "AS IS" basis, without warranty of ** any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR ** IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do ** not allow for the exclusion or limitation of implied warranties, so the above ** limitations or exclusions may not apply to you. IBM shall not be liable for ** any damages you suffer as a result of using, copying, modifying or ** distributing the Sample, even if IBM has been advised of the possibility of ** such damages. ***************************************************************************** ** ** SOURCE FILE NAME: tbread.sqC ** ** SAMPLE: How to read tables ** ** SQL STATEMENTS USED: ** DECLARE CURSOR ** OPEN ** FETCH ** CLOSE ** PREPARE ** DESCRIBE ** SELECT ** ** ***************************************************************************** ** ** For more information on the sample programs, see the README file. ** ** For information on developing embedded SQL applications see the Developing Embedded SQL Applications book. ** ** For information on using SQL statements, see the SQL Reference. ** ** For the latest information on programming, compiling, and running DB2 ** applications, visit the DB2 Information Center at ** http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp ****************************************************************************/ #include <string.h> #include <sqlenv.h> #include <sqlcodes.h> #include <sqlutil.h> #include "utilemb.h" #if ((__cplusplus >= 199711L) && !defined DB2HP && !defined DB2AIX) || \ (DB2LINUX && (__LP64__ || (__GNUC__ >= 3)) ) #include <iomanip> #include <iostream> using namespace std; #else #include <iomanip.h> #include <iostream.h> #endif EXEC SQL BEGIN DECLARE SECTION; short deptnumb; short maxDeptnumb; char deptname[15]; char orgDeptname[15]; short manager; char division[11]; char location[14]; char deptno[4]; char departmentDeptname[30]; char mgrno[7]; short mgrnoInd; char admrdept[4]; char departmentLocation[17]; short departmentLocationInd; char job[9]; short jobInd; short edlevel; short edlevelInd; double comm; double commSum; short commSumInd; char rcteDeptno[4]; char rcteDeptname[30]; char rcteAdmrdept[4]; char strStmt[100]; double avgSalary; EXEC SQL END DECLARE SECTION; class TbRead { public: // methods to perform SELECT int TbSelectUsingFetchIntoHostVariables(); int TbSelectUsingFetchIntoSQLDA(); int TbSelectUsingDeclareCursor(); int TbSelectUsingPrepareDeclareCursor(); int TbSelectUsingPrepareDescribeDeclareCursor(); private: // the support functions for TbSelectUsingPrepareDescribeDeclareCursor int SqldaInit(struct sqlda **, int); int ColTitlesDisplay(struct sqlda *); short DisplayDataLenGet(short, short); int RowDataMemoryAlloc(struct sqlda *); int RowDataDisplay(struct sqlda *); int CellDataDisplay(char *, short, short *, short, short); int RowDataMemoryFree(struct sqlda *); public: // SELECT types int TbMostSimpleSubselect(); int TbBasicSubselect(); int TbGroupBySubselect(); int TbSubselect(); int TbRowSubselect(); int TbFullselect(); int TbSelectStatement(); int TbBasicSubselectFromMultipleTables(); int TbBasicSubselectFromJoinedTable(); int TbBasicSubselectUsingSubquery(); int TbBasicSubselectUsingCorrelatedSubquery(); int TbSubselectUsingGroupingSets(); int TbSubselectUsingRollup(); int TbSubselectUsingCube(); int TbSelectStatementUsingRecursiveCommonTableExpression(); int TbSelectUsingQuerySampling(); private: // support functions for SELECT types int OrgTbContentDisplay(); int DepartmentTbContentDisplay(); int EmployeeTbPartialContentDisplay(); }; int TbRead::TbSelectUsingFetchIntoHostVariables() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT USING FETCH INTO HOST VARIABLES." << endl; cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c0 CURSOR FOR SELECT deptnumb, deptname FROM org; // open cursor EXEC SQL OPEN c0; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c0 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c0 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c0; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSelectUsingFetchIntoHostVariables int TbRead::TbSelectUsingFetchIntoSQLDA() { int rc = 0; struct sqlca sqlca; struct sqlda *pSqlda = NULL; short deptnumbInd; char deptnameInd; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT USING FETCH INTO SQLDA." << endl; cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c1 CURSOR FOR SELECT deptnumb, deptname FROM org; // open cursor EXEC SQL OPEN c1; EMB_SQL_CHECK("cursor -- open"); // initialize SQLDA structure pSqlda = new sqlda[2]; // two variables strncpy(pSqlda->sqldaid, "SQLDA ", sizeof(pSqlda->sqldaid)); pSqlda->sqldabc = (sqlint32) SQLDASIZE(2); pSqlda->sqln = 2; // two variables pSqlda->sqld = 2; pSqlda->sqlvar[0].sqltype = SQL_TYP_NSMALL; pSqlda->sqlvar[0].sqllen = sizeof(short); pSqlda->sqlvar[0].sqldata = (char *)&deptnumb; pSqlda->sqlvar[0].sqlind = (short *)&deptnumbInd; pSqlda->sqlvar[1].sqltype = SQL_TYP_NCSTR; pSqlda->sqlvar[1].sqllen = 15; pSqlda->sqlvar[1].sqldata = (char *)&deptname; pSqlda->sqlvar[1].sqlind = (short *)&deptnameInd; // fetch cursor EXEC SQL FETCH c1 USING DESCRIPTOR :*pSqlda; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c1 USING DESCRIPTOR :*pSqlda; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c1; EMB_SQL_CHECK("cursor -- close"); // release memory allocated delete [] pSqlda; return 0; } //TbRead::TbSelectUsingFetchIntoSQLDA int TbRead::TbSelectUsingDeclareCursor() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT USING DECLARE CURSOR." << endl; cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c2 CURSOR FOR SELECT deptnumb, deptname FROM org; // open cursor EXEC SQL OPEN c2; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c2 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c2 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c2; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSelectUsingDeclareCursor int TbRead::TbSelectUsingPrepareDeclareCursor() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " PREPARE" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT USING PREPARE-DECLARE CURSOR." << endl; cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; strcpy(strStmt, "SELECT deptnumb, deptname FROM org"); EXEC SQL PREPARE stmt1 FROM :strStmt; EMB_SQL_CHECK("statement -- prepare"); // declare cursor EXEC SQL DECLARE c3 CURSOR FOR stmt1; // open cursor EXEC SQL OPEN c3; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c3 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c3 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c3; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSelectUsingPrepareDeclareCursor int TbRead::TbSelectUsingPrepareDescribeDeclareCursor() { int rc = 0; struct sqlca sqlca; struct sqlda *pSqlda = NULL; int numCols; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " PREPARE" << endl; cout << " DESCRIBE" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT USING PREPARE-DESCRIBE-DECLARE CURSOR." << endl; strcpy(strStmt, "SELECT * FROM staff WHERE id <= 30"); cout << "\n Perform:" << endl; cout << " " << strStmt << endl << endl; // ------------------------------------- // detetmine number of output columns // ------------------------------------- EXEC SQL PREPARE stmt2 FROM :strStmt; EMB_SQL_CHECK("statement -- prepare"); rc = SqldaInit(&pSqlda, 1); if (rc != 0) { return rc; } EXEC SQL DESCRIBE stmt2 INTO :*pSqlda; if (sqlca.sqlcode != 0 && sqlca.sqlcode != SQL_RC_W236 && sqlca.sqlcode != SQL_RC_W237 && sqlca.sqlcode != SQL_RC_W238 && sqlca.sqlcode != SQL_RC_W239) { EMB_SQL_CHECK("statement -- describe"); } numCols = (int)pSqlda->sqld; delete [] pSqlda; // ------------------- // invoke statement // ------------------- if (numCols > 0) { if (sqlca.sqlcode == 0 || sqlca.sqlcode == SQL_RC_W236) { rc = SqldaInit(&pSqlda, numCols); if (rc != 0) { return rc; } } if (sqlca.sqlcode == SQL_RC_W237 || sqlca.sqlcode == SQL_RC_W238 || sqlca.sqlcode == SQL_RC_W239) { rc = SqldaInit(&pSqlda, numCols * 2); if (rc != 0) { return rc; } } EXEC SQL DESCRIBE stmt2 INTO :*pSqlda; EMB_SQL_CHECK("statement -- describe"); rc = ColTitlesDisplay(pSqlda); EXEC SQL DECLARE c4 CURSOR FOR stmt2; EXEC SQL OPEN c4; EMB_SQL_CHECK("cursor -- open"); rc = RowDataMemoryAlloc(pSqlda); if (rc != 0) { return rc; } EXEC SQL FETCH c4 USING DESCRIPTOR :*pSqlda; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { rc = RowDataDisplay(pSqlda); EXEC SQL FETCH c4 USING DESCRIPTOR :*pSqlda; EMB_SQL_CHECK("cursor -- fetch"); } EXEC SQL CLOSE c4; EMB_SQL_CHECK("cursor -- close"); rc = RowDataMemoryFree(pSqlda); delete [] pSqlda; } return 0; } //TbRead::TbSelectUsingPrepareDescribeDeclareCursor int TbRead::SqldaInit(struct sqlda **ppSqlda, int size) { int rc = 0; *ppSqlda = new sqlda[size]; if (*ppSqlda == NULL) { return 1; } memcpy((*ppSqlda)->sqldaid, "SQLDA ", 8); (*ppSqlda)->sqldabc = (sqlint32) SQLDASIZE(size); (*ppSqlda)->sqln = size; (*ppSqlda)->sqld = 0; return 0; } //TbRead::SqldaInit int TbRead::ColTitlesDisplay(struct sqlda *pSqlda) { int rc = 0; short colNb; short numCols; short colDataLen; short colTitleLen; short colWidth; char colTitle[129]; numCols = pSqlda->sqld; for (colNb = 0; colNb < numCols; colNb++) { colDataLen = DisplayDataLenGet(pSqlda->sqlvar[colNb].sqltype, pSqlda->sqlvar[colNb].sqllen); colTitleLen = pSqlda->sqlvar[colNb].sqlname.length; colWidth = max(colDataLen, colTitleLen); strcpy(colTitle, pSqlda->sqlvar[colNb].sqlname.data); cout << setw(colWidth) << colTitle; cout << " | "; } cout << endl; return 0; } //TbRead::ColTitlesDisplay short TbRead::DisplayDataLenGet(short sqlDataType, short sqlDataSize) { short displayDataLen; switch (sqlDataType) { case SQL_TYP_DATE: case SQL_TYP_NDATE: case SQL_TYP_TIME: case SQL_TYP_NTIME: case SQL_TYP_STAMP: case SQL_TYP_NSTAMP: case SQL_TYP_VARCHAR: case SQL_TYP_NVARCHAR: case SQL_TYP_CHAR: case SQL_TYP_NCHAR: case SQL_TYP_LONG: case SQL_TYP_NLONG: case SQL_TYP_CSTR: case SQL_TYP_NCSTR: case SQL_TYP_LSTR: case SQL_TYP_NLSTR: displayDataLen = sqlDataSize; break; case SQL_TYP_FLOAT: case SQL_TYP_NFLOAT: // 3 chars for every byte + // 1 char for sign + // 1 digit for decimal point displayDataLen = (short)(3 * sqlDataSize + 1 + 1); break; case SQL_TYP_INTEGER: case SQL_TYP_NINTEGER: case SQL_TYP_SMALL: case SQL_TYP_NSMALL: // 3 chars for every byte + // 1 char for sign displayDataLen = (short)(3 * sqlDataSize + 1); break; case SQL_TYP_DECIMAL: case SQL_TYP_NDECIMAL: displayDataLen = (short)(((char *)&sqlDataSize)[0]) + // precision (short)1 + // decimal point (short)1; // sign break; case SQL_TYP_CGSTR: case SQL_TYP_NCGSTR: case SQL_TYP_VARGRAPH: case SQL_TYP_NVARGRAPH: case SQL_TYP_GRAPHIC: case SQL_TYP_NGRAPHIC: case SQL_TYP_LONGRAPH: case SQL_TYP_NLONGRAPH: displayDataLen = 30; break; case SQL_TYP_BLOB: case SQL_TYP_NBLOB: case SQL_TYP_CLOB: case SQL_TYP_NCLOB: case SQL_TYP_DBCLOB: case SQL_TYP_NDBCLOB: displayDataLen = 30; break; default: displayDataLen = 0; break; } return displayDataLen; } //TbRead::DisplayDataLenGet int TbRead::RowDataMemoryAlloc(struct sqlda *pSqlda) { int rc = 0; short colNb; short numCols; unsigned int memSize; short precision; numCols = pSqlda->sqld; for (colNb = 0; colNb < numCols; colNb++) { // allocate sqlind memory if (pSqlda->sqlvar[colNb].sqltype & 1) { pSqlda->sqlvar[colNb].sqlind = new short; if (pSqlda->sqlvar[colNb].sqlind == NULL) { return 1; } memset(pSqlda->sqlvar[colNb].sqlind, '\0', sizeof(short)); } // allocate sqldata memory switch (pSqlda->sqlvar[colNb].sqltype) { case SQL_TYP_DATE: case SQL_TYP_NDATE: case SQL_TYP_TIME: case SQL_TYP_NTIME: case SQL_TYP_STAMP: case SQL_TYP_NSTAMP: case SQL_TYP_VARCHAR: case SQL_TYP_NVARCHAR: case SQL_TYP_CHAR: case SQL_TYP_NCHAR: case SQL_TYP_LONG: case SQL_TYP_NLONG: case SQL_TYP_CSTR: case SQL_TYP_NCSTR: case SQL_TYP_LSTR: case SQL_TYP_NLSTR: pSqlda->sqlvar[colNb].sqltype = SQL_TYP_NCSTR; memSize = (unsigned int)pSqlda->sqlvar[colNb].sqllen; break; case SQL_TYP_FLOAT: case SQL_TYP_NFLOAT: case SQL_TYP_INTEGER: case SQL_TYP_NINTEGER: case SQL_TYP_SMALL: case SQL_TYP_NSMALL: memSize = (unsigned int)pSqlda->sqlvar[colNb].sqllen; break; case SQL_TYP_DECIMAL: case SQL_TYP_NDECIMAL: precision = (short)(((char *)&(pSqlda->sqlvar[colNb].sqllen))[0]); memSize = (unsigned int)(precision / 2 + 1); break; case SQL_TYP_CGSTR: case SQL_TYP_NCGSTR: case SQL_TYP_VARGRAPH: case SQL_TYP_NVARGRAPH: case SQL_TYP_GRAPHIC: case SQL_TYP_NGRAPHIC: case SQL_TYP_LONGRAPH: case SQL_TYP_NLONGRAPH: memSize = (unsigned int)(2 * pSqlda->sqlvar[colNb].sqllen); break; case SQL_TYP_BLOB: case SQL_TYP_NBLOB: case SQL_TYP_CLOB: case SQL_TYP_NCLOB: memSize = GETSQLDALONGLEN(pSqlda, colNb); break; case SQL_TYP_DBCLOB: case SQL_TYP_NDBCLOB: memSize = 2 * GETSQLDALONGLEN(pSqlda, colNb); break; default: memSize = 0; break; } pSqlda->sqlvar[colNb].sqldata = new char[memSize]; if (pSqlda->sqlvar[colNb].sqldata == NULL) { return 1; } memset(pSqlda->sqlvar[colNb].sqldata, '\0', memSize); } return 0; } //TbRead::RowDataMemoryAlloc int TbRead::RowDataDisplay(struct sqlda *pSqlda) { int rc = 0; short colNb; short numCols; short colDataLen; short colTitleLen; short colWidth; numCols = pSqlda->sqld; for (colNb = 0; colNb < numCols; colNb++) { colDataLen = DisplayDataLenGet(pSqlda->sqlvar[colNb].sqltype, pSqlda->sqlvar[colNb].sqllen); colTitleLen = pSqlda->sqlvar[colNb].sqlname.length; colWidth = max(colDataLen, colTitleLen); rc = CellDataDisplay(pSqlda->sqlvar[colNb].sqldata, pSqlda->sqlvar[colNb].sqltype, pSqlda->sqlvar[colNb].sqlind, pSqlda->sqlvar[colNb].sqllen, colWidth); cout << " | "; } cout << endl; return 0; } //TbRead::RowDataDisplay int TbRead::CellDataDisplay(char *sqldata, short sqltype, short *sqlind, short sqllen, short colWidth) { int rc = 0; char buf[100]; char data[10]; struct lstr { char len; char *data; } *pLstr; int i; short precision; short scale; short numBytes; short top; short bottom; short byteNb; short digNb; struct lob { sqlint32 len; char *data; } *pLob; if (sqltype & 1 && *sqlind < 0) { cout << setw(colWidth) << " -"; } else { switch (sqltype) { case SQL_TYP_DATE: case SQL_TYP_NDATE: case SQL_TYP_TIME: case SQL_TYP_NTIME: case SQL_TYP_STAMP: case SQL_TYP_NSTAMP: case SQL_TYP_VARCHAR: case SQL_TYP_NVARCHAR: case SQL_TYP_CHAR: case SQL_TYP_NCHAR: case SQL_TYP_LONG: case SQL_TYP_NLONG: case SQL_TYP_CSTR: case SQL_TYP_NCSTR: cout.setf(ios::left, ios::adjustfield); memset(data, '\0', sizeof(data)); strncpy(data, sqldata, sqllen); cout << setw(colWidth) << data; break; case SQL_TYP_LSTR: case SQL_TYP_NLSTR: pLstr = (struct lstr *)sqldata; for (i = 0; i < (int)pLstr->len; i++) { cout << (pLstr->data)[i]; } while (i < colWidth) { cout << " "; i = i + 1; } break; case SQL_TYP_FLOAT: case SQL_TYP_NFLOAT: cout << setw(colWidth) << *((double *)sqldata); break; case SQL_TYP_INTEGER: case SQL_TYP_NINTEGER: cout << setw(colWidth) << *((long *)sqldata); break; case SQL_TYP_SMALL: case SQL_TYP_NSMALL: cout.setf(ios::right, ios::adjustfield); cout << setw(colWidth) << *((short *)sqldata); break; case SQL_TYP_DECIMAL: case SQL_TYP_NDECIMAL: precision = (short)(((char *)&sqllen)[0]); scale = (short)(((char *)&sqllen)[1]); // adjust precision to odd value if ((precision % 2) == 0) { precision = precision + 1; } // calculate numBytes numBytes = (short)(precision + 1) / 2; // determine sign using bottom of the last byte bottom = *(sqldata + numBytes - 1) & 0x000F; i = 0; if (bottom == 0x000D || bottom == 0x000B) { buf[i] = '-'; i++; } else { buf[i] = ' '; i++; } // prepare decimal number digNb = 0; if (digNb == precision - scale) { buf[i] = '.'; i++; } // (top + bottom) from first (numBytes - 1) bytes ... for (byteNb = 0; byteNb < numBytes - 1; byteNb = byteNb + 1) { top = *(sqldata + byteNb) & 0x00F0; top = top >> 4; bottom = *(sqldata + byteNb) & 0x000F; buf[i] = top + '0'; i++; digNb++; if (digNb == precision - scale) { buf[i] = '.'; i++; } buf[i] = bottom + '0'; i++; digNb++; if (digNb == precision - scale) { buf[i] = '.'; i++; } } // ... and top of the last byte(bottom is the sign) top = *(sqldata + byteNb) & 0x00F0; top = top >> 4; buf[i] = top + '0'; i++; digNb++; if (digNb == precision - scale) { buf[i] = '.'; i++; } // display decimal number buf[i] = '\0'; cout.setf(ios::left, ios::adjustfield); cout << setw(colWidth) << buf; break; case SQL_TYP_CGSTR: case SQL_TYP_NCGSTR: case SQL_TYP_VARGRAPH: case SQL_TYP_NVARGRAPH: case SQL_TYP_GRAPHIC: case SQL_TYP_NGRAPHIC: case SQL_TYP_LONGRAPH: case SQL_TYP_NLONGRAPH: //cout << setw(colWidth); cout << "Graphic data length: " << setw(5) << sqllen; break; case SQL_TYP_BLOB: case SQL_TYP_NBLOB: case SQL_TYP_CLOB: case SQL_TYP_NCLOB: case SQL_TYP_DBCLOB: case SQL_TYP_NDBCLOB: pLob = (struct lob *)sqldata; //cout << setw(colWidth); if (*sqlind == 0) { cout << "LOB length: " << setw(10) << (long)pLob->len; } else { cout << "Truncated LOB length: " << setw(10) << (long)pLob->len; } break; default: cout << setw(colWidth) << "?"; break; } } return 0; } //TbRead::CellDataDisplay int TbRead::RowDataMemoryFree(struct sqlda *pSqlda) { int rc = 0; short colNb; for (colNb = 0; colNb < pSqlda->sqld; colNb++) { delete [] pSqlda->sqlvar[colNb].sqldata; if (pSqlda->sqlvar[colNb].sqltype & 1) { delete pSqlda->sqlvar[colNb].sqlind; } } return 0; } //TbRead::RowDataMemoryFree int TbRead::TbMostSimpleSubselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SIMPLE SUBSELECT." << endl; // display ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c5 CURSOR FOR SELECT deptnumb, deptname FROM org; // open cursor EXEC SQL OPEN c5; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c5 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c5 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c5; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbMostSimpleSubselect int TbRead::TbBasicSubselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SUBSELECT." << endl; // display content of ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname FROM org"; cout << " WHERE deptnumb < 30" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c6 CURSOR FOR SELECT deptnumb, deptname FROM org WHERE deptnumb < 30; // open cursor EXEC SQL OPEN c6; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c6 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c6 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c6; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbBasicSubselect int TbRead::TbGroupBySubselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM 'GROUP BY' SUBSELECT." << endl; // display the content of ORG table rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT division, MAX(deptnumb) FROM org"; cout << " GROUP BY division" << endl; cout << "\n Results:" << endl; cout << " DIVISION MAX(DEPTNUMB)" << endl; cout << " ---------- --------------" << endl; // declare cursor EXEC SQL DECLARE c7 CURSOR FOR SELECT division, MAX(deptnumb) FROM org GROUP BY division; // open cursor EXEC SQL OPEN c7; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c7 INTO :division, :maxDeptnumb; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(10) << division; cout.setf(ios::right, ios::adjustfield); cout << " " << setw(14) << maxDeptnumb << endl; EXEC SQL FETCH c7 INTO :division, :maxDeptnumb; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c7; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbGroupBySubselect int TbRead::TbSubselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SUBSELECT." << endl; // display the content of ORG table rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT division, MAX(deptnumb)" << endl; cout << " FROM org" << endl; cout << " WHERE location NOT IN 'New York'" << endl; cout << " GROUP BY division"; cout << " HAVING division LIKE '%ern'" << endl; cout << "\n Results:" << endl; cout << " DIVISION MAX(DEPTNUMB)" << endl; cout << " ---------- --------------" << endl; // declare cursor EXEC SQL DECLARE c8 CURSOR FOR SELECT division, MAX(deptnumb) FROM org WHERE location NOT IN 'New York' GROUP BY division HAVING division LIKE '%ern'; // open cursor EXEC SQL OPEN c8; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c8 INTO :division, :maxDeptnumb; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(10) << division; cout.setf(ios::right, ios::adjustfield); cout << " " << setw(14) << maxDeptnumb << endl; EXEC SQL FETCH c8 INTO :division, :maxDeptnumb; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c8; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSubselect int TbRead::TbRowSubselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM 'ROW' SUBSELECT." << endl; // display the content of ORG table rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname INTO :deptnumb, :deptname" << endl; cout << " FROM org" << endl; cout << " WHERE location = 'New York'" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL SELECT deptnumb, deptname INTO :deptnumb, :deptname FROM org WHERE location = 'New York'; cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; return 0; } //TbRead::TbRowSubselect int TbRead::TbFullselect() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM FULLSELECT." << endl; // display ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname" << endl; cout << " FROM org" << endl; cout << " WHERE deptnumb < 20 UNION VALUES(7, 'New Deptname')" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c9 CURSOR FOR SELECT deptnumb, deptname FROM org WHERE deptnumb < 20 UNION VALUES(7, 'New Deptname'); // open cursor EXEC SQL OPEN c9; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c9 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c9 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c9; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbFullselect int TbRead::TbSelectStatement() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT STATEMENT." << endl; // display ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " WITH new_org(new_deptnumb, new_deptname)" << endl; cout << " AS(SELECT deptnumb, deptname" << endl; cout << " FROM org" << endl; cout << " UNION VALUES(7, 'New Dept 1')," << endl; cout << " (77, 'New Dept 2')," << endl; cout << " (777, 'New Dept 3'))" << endl; cout << " SELECT new_deptnumb, new_deptname" << endl; cout << " FROM new_org" << endl; cout << " WHERE new_deptnumb > 70" << endl; cout << " ORDER BY new_deptname" << endl; cout << "\n Results:" << endl; cout << " NEW_DEPTNUMB NEW_DEPTNAME" << endl; cout << " ------------ ------------" << endl; // declare cursor EXEC SQL DECLARE c10 CURSOR FOR WITH new_org(new_deptnumb, new_deptname) AS(SELECT deptnumb, deptname FROM org UNION VALUES(7, 'New Dept 1'), (77, 'New Dept 2'), (777, 'New Dept 3')) SELECT new_deptnumb, new_deptname FROM new_org WHERE new_deptnumb > 70 ORDER BY new_deptname; // open cursor EXEC SQL OPEN c10; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c10 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(12) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(18) << deptname << endl; EXEC SQL FETCH c10 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c10; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSelectStatement int TbRead::TbBasicSubselectFromMultipleTables() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SUBSELECT FROM MULTIPLE TABLES." << endl; // display ORG table content rc = OrgTbContentDisplay(); // display DEPARTMENT table content rc = DepartmentTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, o.deptname, deptno, d.deptname" << endl; cout << " FROM org o, department d" << endl; cout << " WHERE deptnumb <= 15 AND deptno LIKE '%11'" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB ORG.DEPTNAME DEPTNO DEPARTMENT.DEPTNAME" << endl; cout << " -------- -------------- ------ ---------------------" << endl; // declare cursor EXEC SQL DECLARE c11 CURSOR FOR SELECT deptnumb, o.deptname, deptno, d.deptname FROM org o, department d WHERE deptnumb <= 15 AND deptno LIKE '%11'; // open cursor EXEC SQL OPEN c11; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c11 INTO :deptnumb, :orgDeptname, :deptno, :departmentDeptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << orgDeptname << " " << setw(6) << deptno << " " << setw(14) << departmentDeptname << endl; EXEC SQL FETCH c11 INTO :deptnumb, :orgDeptname, :deptno, :departmentDeptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c11; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbBasicSelectFromMultipleTables int TbRead::TbBasicSubselectFromJoinedTable() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SUBSELECT FROM A JOINED TABLE." << endl; // display ORG table content rc = OrgTbContentDisplay(); // display DEPARTMENT table content rc = DepartmentTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, manager, deptno, mgrno" << endl; cout << " FROM org INNER JOIN department" << endl; cout << " ON manager = INTEGER(mgrno)" << endl; cout << " WHERE deptnumb BETWEEN 20 AND 100" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB MANAGER DEPTNO MGRNO" << endl; cout << " -------- ------- ------ ------" << endl; // declare cursor EXEC SQL DECLARE c12 CURSOR FOR SELECT deptnumb, manager, deptno, mgrno FROM org INNER JOIN department ON manager = INTEGER(mgrno) WHERE deptnumb BETWEEN 20 AND 100; // open cursor EXEC SQL OPEN c12; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c12 INTO :deptnumb, :manager, :deptno, :mgrno; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb << " " << setw(7) << manager; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(6) << deptno << " " << setw(6) << mgrno << endl; EXEC SQL FETCH c12 INTO :deptnumb, :manager, :deptno, :mgrno; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c12; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbBasicSubselectFromJoinedTable int TbRead::TbBasicSubselectUsingSubquery() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SUBSELECT USING SUBQUERY." << endl; // display ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname" << endl; cout << " FROM org" << endl; cout << " WHERE deptnumb < (SELECT AVG(deptnumb) FROM org)" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c13 CURSOR FOR SELECT deptnumb, deptname FROM org WHERE deptnumb < (SELECT AVG(deptnumb) FROM org); // open cursor EXEC SQL OPEN c13; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c13 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c13 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c13; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbBasicSubselectUsingSubquery int TbRead::TbBasicSubselectUsingCorrelatedSubquery() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM A SUBSELECT USING CORRELATED SUBQUERY." << endl; // display ORG table content rc = OrgTbContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT deptnumb, deptname" << endl; cout << " FROM org o1" << endl; cout << " WHERE deptnumb > (SELECT AVG(deptnumb)" << endl; cout << " FROM org o2" << endl; cout << " WHERE o2.division = o1.division)" << endl; cout << "\n Results:" << endl; cout << " DEPTNUMB DEPTNAME" << endl; cout << " -------- --------------" << endl; // declare cursor EXEC SQL DECLARE c14 CURSOR FOR SELECT deptnumb, deptname FROM org o1 WHERE deptnumb > (SELECT AVG(deptnumb) FROM org o2 WHERE o2.division = o1.division); // open cursor EXEC SQL OPEN c14; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c14 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname << endl; EXEC SQL FETCH c14 INTO :deptnumb, :deptname; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c14; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbBasicSubselectUsingCorrelatedSubquery int TbRead::TbSubselectUsingGroupingSets() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SUBSELECT USING GROUPING SETS." << endl; rc = EmployeeTbPartialContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT job, edlevel, SUM(comm)" << endl; cout << " FROM employee" << endl; cout << " WHERE job IN('DESIGNER', 'FIELDREP')" << endl; cout << " GROUP BY GROUPING SETS((job, edlevel), (job))" << endl; cout << "\n Results:" << endl; cout << " JOB EDLEVEL SUM(COMM)" << endl; cout << " -------- ------- ----------" << endl; // declare cursor EXEC SQL DECLARE c15 CURSOR FOR SELECT job, edlevel, SUM(comm) FROM employee WHERE job IN('DESIGNER', 'FIELDREP') GROUP BY GROUPING SETS((job, edlevel), (job)); // open cursor EXEC SQL OPEN c15; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c15 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { if (jobInd >= 0) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(8) << job; } else { cout << " - "; } if (edlevelInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(7) << edlevel; } else { cout << " -"; } if (commSumInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(10) << commSum; } else { cout << " - "; } cout << endl; EXEC SQL FETCH c15 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c15; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSubselectUsingGroupingSets int TbRead::TbSubselectUsingRollup() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SUBSELECT USING ROLLUP." << endl; rc = EmployeeTbPartialContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT job, edlevel, SUM(comm)" << endl; cout << " FROM employee" << endl; cout << " WHERE job IN('DESIGNER', 'FIELDREP')" << endl; cout << " GROUP BY ROLLUP(job, edlevel)" << endl; cout << "\n Results:" << endl; cout << " JOB EDLEVEL SUM(COMM)" << endl; cout << " -------- ------- ----------" << endl; // declare cursor EXEC SQL DECLARE c16 CURSOR FOR SELECT job, edlevel, SUM(comm) FROM employee WHERE job IN('DESIGNER', 'FIELDREP') GROUP BY ROLLUP(job, edlevel); // open cursor EXEC SQL OPEN c16; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c16 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { if (jobInd >= 0) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(8) << job; } else { cout << " - "; } if (edlevelInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(7) << edlevel; } else { cout << " -"; } if (commSumInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(10) << commSum; } else { cout << " - "; } cout << endl; EXEC SQL FETCH c16 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c16; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSubselectUsingRollup int TbRead::TbSubselectUsingCube() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SUBSELECT USING CUBE." << endl; rc = EmployeeTbPartialContentDisplay(); cout << "\n Perform:" << endl; cout << " SELECT job, edlevel, SUM(comm)" << endl; cout << " FROM employee" << endl; cout << " WHERE job IN('DESIGNER', 'FIELDREP')" << endl; cout << " GROUP BY CUBE(job, edlevel)" << endl; cout << "\n Results:" << endl; cout << " JOB EDLEVEL SUM(COMM)" << endl; cout << " -------- ------- ----------" << endl; // declare cursor EXEC SQL DECLARE c17 CURSOR FOR SELECT job, edlevel, SUM(comm) FROM employee WHERE job IN('DESIGNER', 'FIELDREP') GROUP BY CUBE(job, edlevel); // open cursor EXEC SQL OPEN c17; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c17 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { if (jobInd >= 0) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(8) << job; } else { cout << " - "; } if (edlevelInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(7) << edlevel; } else { cout << " -"; } if (commSumInd >= 0) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(10) << commSum; } else { cout << " - "; } cout << endl; EXEC SQL FETCH c17 INTO :job:jobInd, :edlevel:edlevelInd, :commSum:commSumInd; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c17; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSubselectUsingCube int TbRead::TbSelectStatementUsingRecursiveCommonTableExpression() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:" << endl; cout << " DECLARE CURSOR" << endl; cout << " OPEN" << endl; cout << " FETCH" << endl; cout << " CLOSE" << endl; cout << "TO PERFORM SELECT STATEMENT" << endl; cout << "USING RECURSIVE COMMON TABLE EXPRESSION." << endl; // display DEPARTMENT table content rc = DepartmentTbContentDisplay(); cout << "\n Perform:"; cout << "\n WITH rcte_department(deptno, deptname, admrdept)"; cout << "\n AS(SELECT root.deptno, root.deptname, root.admrdept"; cout << "\n FROM department root"; cout << "\n WHERE root.deptname = 'SUPPORT SERVICES'"; cout << "\n UNION ALL"; cout << " SELECT child.deptno, child.deptname, child.admrdept"; cout << "\n "; cout << " FROM department child, rcte_department parent"; cout << "\n WHERE child.admrdept = parent.deptno)"; cout << "\n SELECT * FROM rcte_department" << endl; cout << "\n Results:" << endl; cout << " DEPTNO DEPTNAME ADMRDEPT" << endl; cout << " ------ ---------------------------- --------" << endl; // display cursor EXEC SQL DECLARE c18 CURSOR FOR WITH rcte_department(deptno, deptname, admrdept) AS(SELECT root.deptno, root.deptname, root.admrdept FROM department root WHERE root.deptname = 'SUPPORT SERVICES' UNION ALL SELECT child.deptno, child.deptname, child.admrdept FROM department child, rcte_department parent WHERE child.admrdept = parent.deptno) SELECT * FROM rcte_department; // open cursor EXEC SQL OPEN c18; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c18 INTO :rcteDeptno, :rcteDeptname, :rcteAdmrdept; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout << " " << setw(6) << rcteDeptno << " " << setw(28) << rcteDeptname << " " << setw(8) << rcteAdmrdept << endl; EXEC SQL FETCH c18 INTO :rcteDeptno, :rcteDeptname, :rcteAdmrdept; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c18; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::TbSelectStatementUsingRecursiveCommonTableExpression int TbRead::TbSelectUsingQuerySampling() { int rc = 0; struct sqlca sqlca; cout << "\n-----------------------------------------------------------"; cout << "\nUSE THE SQL STATEMENTS:\n"; cout << " DECLARE CURSOR\n"; cout << " OPEN\n"; cout << " FETCH\n"; cout << " CLOSE\n"; cout << "TO PERFORM A SELECT USING QUERY SAMPLING.\n"; cout << "\nCOMPUTING AVG(SALARY) WITHOUT SAMPLING \n"; cout << "\n Perform:\n"; cout << " SELECT AVG(salary) FROM employee \n"; cout << "\n Results:\n"; cout << " AVG SALARY\n"; cout << " ----------\n"; // declare cursor EXEC SQL DECLARE c22 CURSOR FOR SELECT AVG(salary) FROM employee; // open cursor EXEC SQL OPEN c22; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c22 INTO :avgSalary; EMB_SQL_CHECK("cursor -- fetch"); if (sqlca.sqlcode != 100) { cout.precision(2); cout << " " << avgSalary << endl; } // close cursor EXEC SQL CLOSE c22; EMB_SQL_CHECK("cursor -- close"); cout << "\nCOMPUTING AVG(SALARY) WITH QUERY SAMPLING"; cout << "\n - ROW LEVEL SAMPLING "; cout << "\n - BLOCK LEVEL SAMPLING \n"; cout << "\n ROW LEVEL SAMPLING : USE THE KEYWORD 'BERNOULLI'\n"; cout << "\nFOR A SAMPLING PERCENTAGE OF P, EACH ROW OF THE TABLE IS\n"; cout << "SELECTED FOR THE INCLUSION IN THE RESULT WITH A PROBABILITY\n"; cout << "OF P/100, INDEPENDENTLY OF THE OTHER ROWS IN T\n"; cout << "\n Perform:\n"; cout << " SELECT AVG(salary) FROM employee TABLESAMPLE BERNOULLI(25)"; cout << " REPEATABLE(5)\n"; cout << "\n Results:\n"; cout << " AVG SALARY\n"; cout << " ----------\n"; // declare cursor EXEC SQL DECLARE c23 CURSOR FOR SELECT AVG(salary) FROM employee TABLESAMPLE BERNOULLI(25) REPEATABLE(5); // open cursor EXEC SQL OPEN c23; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c23 INTO :avgSalary; EMB_SQL_CHECK("cursor -- fetch"); if (sqlca.sqlcode != 100) { cout.precision(2); cout << " " << avgSalary << endl; } // close cursor EXEC SQL CLOSE c23; EMB_SQL_CHECK("cursor -- close"); cout << "\n\n BLOCK LEVEL SAMPLING : USE THE KEYWORD 'SYSTEM'\n"; cout << "\nFOR A SAMPLING PERCENTAGE OF P, EACH ROW OF THE TABLE IS\n"; cout << "SELECTED FOR INCLUSION IN THE RESULT WITH A PROBABILITY\n"; cout << "OF P/100, NOT NECESSARILY INDEPENDENTLY OF THE OTHER ROWS\n"; cout << "IN T, BASED UPON AN IMPLEMENTATION-DEPENDENT ALGORITHM\n"; cout << "\n Perform:\n"; cout << " SELECT AVG(salary) FROM employee TABLESAMPLE SYSTEM(50)"; cout << " REPEATABLE(1234)\n"; cout << "\n Results:\n"; cout << " AVG SALARY\n"; cout << " ----------\n"; // declare cursor EXEC SQL DECLARE c24 CURSOR FOR SELECT AVG(salary)FROM employee TABLESAMPLE SYSTEM(50) REPEATABLE(1234); // open cursor EXEC SQL OPEN c24; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c24 INTO :avgSalary; EMB_SQL_CHECK("cursor -- fetch"); if (sqlca.sqlcode != 100) { cout.precision(2); cout << " " << avgSalary << endl; } // close cursor EXEC SQL CLOSE c24; EMB_SQL_CHECK("cursor -- close"); cout << "\nREPEATABLE CLAUSE ENSURES THAT REPEATED EXECUTIONS OF THAT\n"; cout << "TABLE REFERENCE WILL RETURN IDENTICAL RESULTS FOR THE SAME \n"; cout << "VALUE OF THE REPEAT ARGUMENT (IN PARENTHESIS). \n"; return 0; } // TbRead::TbSelectUsingQuerySampling int TbRead::OrgTbContentDisplay() { struct sqlca sqlca; cout << "\n SELECT * FROM org" << endl; cout << " DEPTNUMB DEPTNAME MANAGER DIVISION LOCATION" << endl; cout << " -------- -------------- ------- ---------- --------------" << endl; EXEC SQL DECLARE c19 CURSOR FOR SELECT * FROM org; EXEC SQL OPEN c19; EMB_SQL_CHECK("cursor -- open"); EXEC SQL FETCH c19 INTO :deptnumb, :deptname, :manager, :division, :location; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::right, ios::adjustfield); cout << " " << setw(8) << deptnumb; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(14) << deptname; cout.setf(ios::right, ios::adjustfield); cout << " " << setw(7) << manager; cout.setf(ios::left, ios::adjustfield); cout << " " << setw(10) << division << " " << setw(14) << location << endl; EXEC SQL FETCH c19 INTO :deptnumb, :deptname, :manager, :division, :location; EMB_SQL_CHECK("cursor -- fetch"); } EXEC SQL CLOSE c19; EMB_SQL_CHECK("cursor -- close"); return 0; } // TbRead::OrgTableContentDisplay int TbRead::DepartmentTbContentDisplay() { struct sqlca sqlca; cout << "\n SELECT * FROM department" << endl; cout << " DEPTNO DEPTNAME MGRNO ADMRDEPT LOCATION" << endl; cout << " ------ ---------------------------- ------ -------- --------" << endl; EXEC SQL DECLARE c20 CURSOR FOR SELECT * FROM department; EXEC SQL OPEN c20; EMB_SQL_CHECK("cursor -- open"); EXEC SQL FETCH c20 INTO :deptno, :departmentDeptname, :mgrno:mgrnoInd, :admrdept, :departmentLocation:departmentLocationInd; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(6) << deptno << " " << setw(28) << departmentDeptname; if (mgrnoInd >= 0) { cout << " " << setw(6) << mgrno; } else { cout << " - "; } cout << " " << setw(8) << admrdept; if (departmentLocationInd >= 0) { cout << " " << setw(16) << departmentLocation; } else { cout << " - "; } cout << endl; EXEC SQL FETCH c20 INTO :deptno, :departmentDeptname, :mgrno:mgrnoInd, :admrdept, :departmentLocation:departmentLocationInd; EMB_SQL_CHECK("cursor -- fetch"); } EXEC SQL CLOSE c20; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::DepartmentTbContentDisplay int TbRead::EmployeeTbPartialContentDisplay() { int rc = 0; struct sqlca sqlca; cout << "\n Perform:" << endl; cout << " SELECT job, edlevel, comm" << endl; cout << " FROM employee" << endl; cout << " WHERE job IN('DESIGNER', 'FIELDREP')" << endl; cout << "\n Results:" << endl; cout << " JOB EDLEVEL COMM" << endl; cout << " -------- ------- ----------" << endl; // declare cursor EXEC SQL DECLARE c21 CURSOR FOR SELECT job, edlevel, comm FROM employee WHERE job IN('DESIGNER', 'FIELDREP'); // open cursor EXEC SQL OPEN c21; EMB_SQL_CHECK("cursor -- open"); // fetch cursor EXEC SQL FETCH c21 INTO :job, :edlevel, :comm; EMB_SQL_CHECK("cursor -- fetch"); while (sqlca.sqlcode != 100) { cout.setf(ios::left, ios::adjustfield); cout << " " << setw(8) << job; cout.setf(ios::right, ios::adjustfield); cout << " " << setw(7) << edlevel << " " << setw(10) << comm << endl; EXEC SQL FETCH c21 INTO :job, :edlevel, :comm; EMB_SQL_CHECK("cursor -- fetch"); } // close cursor EXEC SQL CLOSE c21; EMB_SQL_CHECK("cursor -- close"); return 0; } //TbRead::EmployeeTbPartialContentDisplay int main(int argc, char *argv[]) { int rc = 0; CmdLineArgs check; TbRead read; DbEmb db; // check the command line arguments rc = check.CmdLineArgsCheck1(argc, argv, db); if (rc != 0) return rc; cout.setf(ios::fixed, ios::floatfield); cout.precision(2); cout << "\nTHIS SAMPLE SHOWS HOW TO READ TABLES." << endl; cout << "\n THIS SAMPLE SHOWS:" << endl; cout << " - METHODS TO PERFORM SELECT" << endl; cout << " - SELECT TYPES" << endl; cout << " ALL METHODS APPLY TO ALL TYPES, EXCEPTING" << endl; cout << " 'TbRowSubselect' TYPE WHERE THE FOLLOWING METHODS" << endl; cout << " DESCRIBED IN dbuse SAMPLE APPLY:" << endl; cout << " StaticStmtWithHostVarsInvoke" << endl; cout << " CompoundStmtInvoke" << endl; cout << "\n METHODS TO PERFORM SELECT." << endl; cout << " SELECT HAS TWO IMPORTANT PARTS:" << endl; cout << " -DECLARE CURSOR" << endl; cout << " -FETCH CURSOR" << endl; cout << " THERE ARE THREE METHODS TO DECLARE CURSOR:" << endl; cout << " -SIMPLE DECLARE CURSOR" << endl; cout << " -PREPARE-DECLARE CURSOR" << endl; cout << " -PREPARE-DESCRIBE-DECLARE CURSOR" << endl; cout << " THERE ARE TWO METHODS TO FETCH CURSOR:" << endl; cout << " -FETCH INTO HOST VARIABLES" << endl; cout << " -FETCH INTO SQLDA" << endl; // connect to database rc = db.Connect(); if (rc != 0) { return rc; } // methods to perform SELECT cout << "\n***************************************" << endl; cout << " METHODS TO PERFORM SELECT" << endl; cout << "***************************************" << endl; rc = read.TbSelectUsingFetchIntoHostVariables(); rc = read.TbSelectUsingFetchIntoSQLDA(); rc = read.TbSelectUsingDeclareCursor(); rc = read.TbSelectUsingPrepareDeclareCursor(); rc = read.TbSelectUsingPrepareDescribeDeclareCursor(); // SELECT types cout << "\n***************************************" << endl; cout << " SELECT TYPES" << endl; cout << "**************************************" << endl; rc = read.TbMostSimpleSubselect(); rc = read.TbBasicSubselect(); rc = read.TbGroupBySubselect(); rc = read.TbSubselect(); rc = read.TbRowSubselect(); rc = read.TbFullselect(); rc = read.TbSelectStatement(); rc = read.TbBasicSubselectFromMultipleTables(); rc = read.TbBasicSubselectFromJoinedTable(); rc = read.TbBasicSubselectUsingSubquery(); rc = read.TbBasicSubselectUsingCorrelatedSubquery(); rc = read.TbSubselectUsingGroupingSets(); rc = read.TbSubselectUsingRollup(); rc = read.TbSubselectUsingCube(); rc = read.TbSelectStatementUsingRecursiveCommonTableExpression(); rc = read.TbSelectUsingQuerySampling(); // disconnect from the database rc = db.Disconnect(); if (rc != 0) { return rc; } return 0; } // main