C ++ SQL数据库程序
我有以下编写的代码,但SQLBindCol似乎无法正常工作(当然,我也可能搞砸了整个程序!它们在SQL企业管理器中看起来都很不错。因此,在注释"第3部分和第4部分:基于条件的搜索"之后,我需要帮助。也许我应该完成完全不同的任务,或者这是可以接受的方法?
#include <iostream> #include <cstdio> #include <string> #include <windows.h> #include <sql.h> #include <sqlext.h> #include <sqltypes.h> using namespace std; // to save us having to type std:: const int MAX_CHAR = 1024; int main ( ) { SQLCHAR SQLStmt[MAX_CHAR]; char strSQL[MAX_CHAR]; char chrTemp; SQLVARCHAR rtnFirstName[50]; SQLVARCHAR rtnLastName[50]; SQLVARCHAR rtnAddress[30]; SQLVARCHAR rtnCity[30]; SQLVARCHAR rtnState[3]; SQLDOUBLE rtnSalary; SQLVARCHAR rtnGender[1]; SQLINTEGER rtnAge; // Get a handle to the database SQLHENV EnvironmentHandle; RETCODE retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvironmentHandle ); // Set the SQL environment flags retcode = SQLSetEnvAttr( EnvironmentHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ); // create handle to the SQL database SQLHDBC ConnHandle; retcode = SQLAllocHandle( SQL_HANDLE_DBC, EnvironmentHandle, &ConnHandle ); // Open the database using a System DSN retcode = SQLDriverConnect(ConnHandle, NULL, (SQLCHAR*)"DSN=PRG411;UID=myUser;PWD=myPass;", SQL_NTS, NULL, SQL_NTS, NULL, SQL_DRIVER_NOPROMPT); if (!retcode) { cout << "SQLConnect() Failed"; } else { // create a SQL Statement variable SQLHSTMT StatementHandle; retcode = SQLAllocHandle(SQL_HANDLE_STMT, ConnHandle, &StatementHandle); // Part 1: Create the Employee table (Database) do { cout << "Create the new table? "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == 'y' || chrTemp == 'Y') { strcpy((char *) SQLStmt, "CREATE TABLE [dbo].[Employee]([pkEmployeeID] [int] IDENTITY(1,1) NOT NULL,[FirstName] [varchar](50) NOT NULL,[LastName] [varchar](50) NOT NULL,[Address] [varchar](30) NOT NULL,[City] [varchar](30) NOT NULL,[State] [varchar](3) NOT NULL, [Salary] [double] NOT NULL,[Gender] [varchar](1) NOT NULL, [Age] [int] NOT NULL, CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([pkEmployeeID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); } // Part 2: Hardcode records into the table do { cout << "Add records to the table? "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == 'y' || chrTemp == 'Y') { strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Mike','Slentz','123 Torrey Dr.','North Clairmont','CA', 48000.00 ,'M',34)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Sue','Vander Hayden','46 East West St.','San Diego','CA', 36000.00 ,'F',28)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Sharon','Stonewall','756 West Olive Garden Way','Plymouth','MA', 56000.00 ,'F',58)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('James','Bartholemew','777 Praying Way','Falls Church','VA', 51000.00 ,'M',45)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Joe','Smith','111 North 43rd Ave','Peoria','AZ', 44000.00 ,'M', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Michael','Smith','20344 North Swan Park','Phoenix','AZ', 24000.00 ,'M', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Jennifer','Jones','123 West North Ave','Flagstaff','AZ', 40000.00 ,'F', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Cora','York','33rd Park Way Drive','Mayville','MI', 30000.00 ,'F', 61)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Tom','Jefferson','234 Friendship Way','Battle Creek','MI', 41000.00 ,'M', 31)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); } // Part 3 & 4: Searchs based on criteria do { cout << "1. Display all records in the database" << endl; cout << "2. Display all records with age greater than 40" << endl; cout << "3. Display all records with salary over K" << endl; cout << "4. Exit" << endl << endl; do { cout << "Please enter a selection: "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == '1') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE"); } else if (chrTemp == '2') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE WHERE [AGE] > 40"); } else if (chrTemp == '3') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE WHERE [Salary] > 30000"); } if (chrTemp == '1' || chrTemp == '2' || chrTemp == '3') { retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); SQLBindCol(StatementHandle, 1, SQL_C_CHAR, &rtnFirstName, sizeof(rtnFirstName), NULL ); SQLBindCol(StatementHandle, 2, SQL_C_CHAR, &rtnLastName, sizeof(rtnLastName), NULL ); SQLBindCol(StatementHandle, 3, SQL_C_CHAR, &rtnAddress, sizeof(rtnAddress), NULL ); SQLBindCol(StatementHandle, 4, SQL_C_CHAR, &rtnCity, sizeof(rtnCity), NULL ); SQLBindCol(StatementHandle, 5, SQL_C_CHAR, &rtnState, sizeof(rtnState), NULL ); SQLBindCol(StatementHandle, 6, SQL_C_DOUBLE, &rtnSalary, sizeof(rtnSalary), NULL ); SQLBindCol(StatementHandle, 7, SQL_C_CHAR, &rtnGender, sizeof(rtnGender), NULL ); SQLBindCol(StatementHandle, 8, SQL_C_NUMERIC, &rtnAge, sizeof(rtnAge), NULL ); for(;;) { retcode = SQLFetch(StatementHandle); if (retcode == SQL_NO_DATA_FOUND) break; cout << rtnFirstName << " " << rtnLastName << " " << rtnAddress << " " << rtnCity << " " << rtnState << " " << rtnSalary << " " << rtnGender << "" << rtnAge << endl; } } } while (chrTemp != '4'); SQLFreeStmt(StatementHandle, SQL_CLOSE ); SQLFreeConnect(ConnHandle); SQLFreeEnv(EnvironmentHandle); printf( "Done.\n" ); } return 0; }
解决方案
我们可以从SQL中获得足够的诊断,从而可以隔离和解决问题。
当SQLExecDirect返回" SQL_SUCCESS"或者" SQL_SUCCESS_WITH_INFO"以外的其他值时,可以调用该语句句柄来告诉我们它出了什么问题。
SQLGetDiagRec(SQL_HANDLE_STMT,StatementHandle,req,state,&error,(SQLCHAR *)缓冲区,(SQLINTEGER)MAX_CHAR,(SQLSMALLINT *)&output_length);`
当然,我们必须分配我们在此处看到的变量……我建议我们在SQLGetDiagRec调用之后放置一条废线,并为其分配一个断点。当它中断时,我们可以查看state
的值:它将与此处的"诊断"部分保持一致:
http://msdn.microsoft.com/zh-CN/library/ms713611(VS.85).aspx
好的,这是现在可以使用的代码...
using namespace std; // to save us having to type std:: const int MAX_CHAR = 1024; int main ( ) { SQLSMALLINT RecNumber; SQLCHAR * SQLState; SQLINTEGER * NativeErrorPtr; SQLCHAR * MessageText; SQLSMALLINT BufferLength; SQLSMALLINT * TextLengthPtr; SQLCHAR SQLStmt[MAX_CHAR]; char strSQL[MAX_CHAR]; char chrTemp; SQLVARCHAR rtnFirstName[50]; SQLVARCHAR rtnLastName[50]; SQLVARCHAR rtnAddress[30]; SQLVARCHAR rtnCity[30]; SQLVARCHAR rtnState[3]; SQLDOUBLE rtnSalary; SQLVARCHAR rtnGender[2]; SQLINTEGER rtnAge; // Get a handle to the database SQLHENV EnvironmentHandle; RETCODE retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvironmentHandle ); // Set the SQL environment flags retcode = SQLSetEnvAttr( EnvironmentHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ); // create handle to the SQL database SQLHDBC ConnHandle; retcode = SQLAllocHandle( SQL_HANDLE_DBC, EnvironmentHandle, &ConnHandle ); // Open the database using a System DSN retcode = SQLDriverConnect(ConnHandle, NULL, (SQLCHAR*)"DSN=PRG411;UID=myUser;PWD=myPass;", SQL_NTS, NULL, SQL_NTS, NULL, SQL_DRIVER_NOPROMPT); if (!retcode) { cout << "SQLConnect() Failed"; } else { // create a SQL Statement variable SQLHSTMT StatementHandle; retcode = SQLAllocHandle(SQL_HANDLE_STMT, ConnHandle, &StatementHandle); // Part 1: Create the Employee table (Database) do { cout << "Create the new table? "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == 'y' || chrTemp == 'Y') { strcpy((char *) SQLStmt, "CREATE TABLE [dbo].[Employee]([pkEmployeeID] [int] IDENTITY(1,1) NOT NULL,[FirstName] [varchar](50) NOT NULL,[LastName] [varchar](50) NOT NULL,[Address] [varchar](30) NOT NULL,[City] [varchar](30) NOT NULL,[State] [varchar](3) NOT NULL, [Salary] [decimal] NOT NULL,[Gender] [varchar](1) NOT NULL, [Age] [int] NOT NULL, CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([pkEmployeeID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); } // Part 2: Hardcode records into the table do { cout << "Add records to the table? "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == 'y' || chrTemp == 'Y') { strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Mike','Slentz','123 Torrey Dr.','North Clairmont','CA', 48000.00 ,'M',34)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Sue','Vander Hayden','46 East West St.','San Diego','CA', 36000.00 ,'F',28)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Sharon','Stonewall','756 West Olive Garden Way','Plymouth','MA', 56000.00 ,'F',58)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('James','Bartholemew','777 Praying Way','Falls Church','VA', 51000.00 ,'M',45)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Joe','Smith','111 North 43rd Ave','Peoria','AZ', 44000.00 ,'M', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Michael','Smith','20344 North Swan Park','Phoenix','AZ', 24000.00 ,'M', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Jennifer','Jones','123 West North Ave','Flagstaff','AZ', 40000.00 ,'F', 40)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Cora','York','33rd Park Way Drive','Mayville','MI', 30000.00 ,'F', 61)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); strcpy((char *) SQLStmt, "INSERT INTO employee([FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age]) VALUES ('Tom','Jefferson','234 Friendship Way','Battle Creek','MI', 41000.00 ,'M', 31)"); retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); } // Part 3 & 4: Searchs based on criteria do { cout << "1. Display all records in the database" << endl; cout << "2. Display all records with age 40 or over" << endl; cout << "3. Display all records with salary K or over" << endl; cout << "4. Exit" << endl << endl; do { cout << "Please enter a selection: "; cin >> chrTemp; } while (cin.fail()); if (chrTemp == '1') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE"); } else if (chrTemp == '2') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE WHERE [AGE] >= 40"); } else if (chrTemp == '3') { strcpy((char *) SQLStmt, "SELECT [FirstName], [LastName], [Address], [City], [State], [Salary], [Gender],[Age] FROM EMPLOYEE WHERE [Salary] >= 30000"); } if (chrTemp == '1' || chrTemp == '2' || chrTemp == '3') { retcode = SQLExecDirect(StatementHandle, SQLStmt, SQL_NTS); //SQLGetDiagRec(SQL_HANDLE_STMT, StatementHandle, RecNumber, SQLState, NativeErrorPtr, (SQLCHAR*) MessageText, (SQLINTEGER) BufferLength, (SQLSMALLINT*) &TextLengthPtr); SQLBindCol(StatementHandle, 1, SQL_C_CHAR, &rtnFirstName, sizeof(rtnFirstName), NULL ); SQLBindCol(StatementHandle, 2, SQL_C_CHAR, &rtnLastName, sizeof(rtnLastName), NULL ); SQLBindCol(StatementHandle, 3, SQL_C_CHAR, &rtnAddress, sizeof(rtnAddress), NULL ); SQLBindCol(StatementHandle, 4, SQL_C_CHAR, &rtnCity, sizeof(rtnCity), NULL ); SQLBindCol(StatementHandle, 5, SQL_C_CHAR, &rtnState, sizeof(rtnState), NULL ); SQLBindCol(StatementHandle, 6, SQL_C_DOUBLE, &rtnSalary, sizeof(rtnSalary), NULL ); SQLBindCol(StatementHandle, 7, SQL_C_CHAR, &rtnGender, sizeof(rtnGender), NULL ); SQLBindCol(StatementHandle, 8, SQL_C_LONG, &rtnAge, sizeof(rtnAge), NULL ); for(;;) { retcode = SQLFetch(StatementHandle); if (retcode == SQL_NO_DATA_FOUND) break; cout << rtnFirstName << " " << rtnLastName << " " << rtnAddress << " " << rtnCity << " " << rtnState << " " << rtnSalary << " " << rtnGender << " " << rtnAge << endl; } SQLFreeStmt(StatementHandle, SQL_CLOSE); } } while (chrTemp != '4'); SQLFreeStmt(StatementHandle, SQL_CLOSE ); SQLFreeHandle(SQL_HANDLE_STMT, StatementHandle); SQLDisconnect(ConnHandle); SQLFreeHandle(SQL_HANDLE_DBC, ConnHandle); SQLFreeHandle(SQL_HANDLE_ENV, EnvironmentHandle); printf( "Done.\n" ); } return 0; }
我们说我们在以下方面遇到错误:
string sqlString ="选择*来自客户,其中Customers.Employee ='" + id +"'";
很明显,对不起,大声笑。 ID是整数,确定。但是,当我们评估字符串时,它像这样出现:
string sqlString ="选择*从客户中,如果Customers.Employee ='100'";
注意到出什么事了吗?我们周围有单引号。因此,无论使用哪种数据类型,单引号都会使SQL将其视为字符串。因此,像这样将它们取出:
string sqlString ="选择来自客户,其中Customer.Employee =" + id +"";
。 。 。 。 。 。 。或者,
字符串sqlString ="从客户那里选择Wheres.Customers.Employee =" + id;
我的问题是...我们能解释一下C ++中记录的循环工作原理吗?例如,用户向strUName输入用户名,并且我们想查看该用户名是否在数据库表Users中。 SQL很容易(从[UName] ='" + strUName +"'的用户中选择*;但是如何在C ++中实际执行它并弄清楚呢?
我看到了SQLStmt,看到它正在使用Direct执行。然后,我看到一些SQLBindCol垃圾,然后是一个无限循环,直到破坏evals。但是我不太了解正在发生的事情(这对我来说对于任何其他语言来说都很容易,但是我对C ++还是陌生的。