mysql connector 教程_MySQL Connector/C++入門教程(上)

目錄

MySQL C++ Driver的實現基于JDBC4.0規范

安裝MySQL Connector/C++

運行時依賴

C++ IDE

為示例程序創建數據庫與數據表

使用Connector/C++測試數據庫連接

使用prepared Statements

使用事務

訪問Result Set Metadata

訪問Database Metadata

通過PreparedStatment對象訪問參數元數據

捕獲異常

調試/跟蹤 MySQL Connector/C++

更多信息

MySQL C++ Driver的實現基于JDBC4.0規范

MySQL Connector/C++是由Sun Microsystems開發的MySQL連接器。它提供了基于OO的編程接口與數據庫驅動來操作MySQL服務器。

與許多其他現存的C++接口實現不同,Connector/C++遵循了JDBC規范。也就是說,Connector/C++ Driver的API主要是基于Java語言的JDBC接口。JDBC是java語言與各種數據庫連接的標準工業接口。Connector/C++實現了大部分JDBC4.0規范。如果C++程序的開發者很熟悉JDBC編程,將很快的入門。

MySQL Connector/C++實現了下面這些類:

Driver

Connection

Statement

PreparedStatement

ResultSet

Savepoint

DatabaseMetaData

ResultSetMetaData

ParameterMetaData

Connector/C++可用于連接MySQL5.1及其以后版本。

在MySQL Connector/C++發布之前,C++程序員可以使用MySQL C API或者MySQL++訪問MySQL。前者是非標準、過程化的C API,后者是對MySQL C API的C++封裝。

安裝MySQL Connector/C++

此處略。(譯者注:用戶可以到MySQL的官網[http://dev.mysql.com/downloads/connector/cpp/1.0.html]去下載MySQL Connector/C++的安裝程序,或者只下載dll,或者下載源代碼自己編譯。筆者在Window平臺上使用MySQL,下載了mysql-connector-c++-noinstall-1.0.5-win32這個版本用于調試。)

運行時依賴

MySQL Connector/C++ Driver依賴MySQL的客戶端庫,在MySQL安裝目錄下的lib\opt\libmysql.dll。如果是通過安裝程序來安裝MySQL Connector/C++,libmysql會一并安裝,如果從官網只下載了dll或源碼,在使用時,程序必須鏈接到libmysql.dll。

C++ IDE

此處略。(譯者注:原文作者使用NetBean作為C++的IED。筆者使用VS2008)

為示例程序創建數據庫與數據表

(譯者注:此節略掉許多不太重要的內容。)在MySQL中創建test數據庫,使用下面語句創建數據表:City:

Create Table: CREATE TABLE `City` ( `CityName` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=ascii

然后向City表中添加一些數據。最后表的內容為:

mysql>SELECT * FROM City;

+--------------------+

| CityName |

+--------------------+

| Hyderabad, India |

| San Francisco, USA

|

| Sydney, Australia |

+--------------------+

3 rows in set (0.17 sec)

使用Connector/C++測試數據庫連接

下面的代碼演示如何使用Connector/C++連接到MySQL服務器:

連接到test數據庫;

執行一個查詢獲取City表中的數據,顯示在控制臺上;

使用Prepared Statements向City表插入數據;

使用savepoints演示事務;

獲取結果集和數據庫的元信息;

例子代碼僅僅用于演示,不建議讀者在實際開發中使用這種樣式的代碼。(譯者注:例子代碼很長,如果看不太明白,沒關系,等閱讀完全文之后再回過頭來看)

#include

#include

#include

#include

#include "mysql_driver.h"

#include "mysql_connection.h"

#include "cppconn/driver.h"

#include "cppconn/statement.h"

#include "cppconn/prepared_statement.h"

#include "cppconn/metadata.h"

#include "cppconn/exception.h"

#define DBHOST "tcp://127.0.0.1:3306"

#define USER "root"

#define PASSWORD "000000"

#define DATABASE "test"

#define NUMOFFSET 100

#define COLNAME 200

using namespace std;

using namespace sql;

#pragma comment(lib, "mysqlcppconn.lib")

void Demo();

int main(int argc, char *argv[])

{

Demo();

return 0;

}

/* 獲取數據庫信息 */

static void GetDBMetaData(Connection *dbcon)

{

if (dbcon->isClosed())

{

throw runtime_error("DatabaseMetaData FAILURE - database connection closed");

}

cout << "\nDatabase Metadata" << endl;

cout << "-----------------" << endl;

cout << boolalpha;

/* The following commented statement won't work with Connector/C++ 1.0.5 and later */

//auto_ptr < DatabaseMetaData > dbcon_meta (dbcon->getMetaData());

DatabaseMetaData *dbcon_meta = dbcon->getMetaData();

cout << "Database Product Name: " << dbcon_meta->getDatabaseProductName() << endl;

cout << "Database Product Version: " << dbcon_meta->getDatabaseProductVersion() << endl;

cout << "Database User Name: " << dbcon_meta->getUserName() << endl << endl;

cout << "Driver name: " << dbcon_meta->getDriverName() << endl;

cout << "Driver version: " << dbcon_meta->getDriverVersion() << endl << endl;

cout << "Database in Read-Only Mode?: " << dbcon_meta->isReadOnly() << endl;

cout << "Supports Transactions?: " << dbcon_meta->supportsTransactions() << endl;

cout << "Supports DML Transactions only?: " << dbcon_meta->supportsDataManipulationTransactionsOnly() << endl;

cout << "Supports Batch Updates?: " << dbcon_meta->supportsBatchUpdates() << endl;

cout << "Supports Outer Joins?: " << dbcon_meta->supportsOuterJoins() << endl;

cout << "Supports Multiple Transactions?: " << dbcon_meta->supportsMultipleTransactions() << endl;

cout << "Supports Named Parameters?: " << dbcon_meta->supportsNamedParameters() << endl;

cout << "Supports Statement Pooling?: " << dbcon_meta->supportsStatementPooling() << endl;

cout << "Supports Stored Procedures?: " << dbcon_meta->supportsStoredProcedures() << endl;

cout << "Supports Union?: " << dbcon_meta->supportsUnion() << endl << endl;

cout << "Maximum Connections: " << dbcon_meta->getMaxConnections() << endl;

cout << "Maximum Columns per Table: " << dbcon_meta->getMaxColumnsInTable() << endl;

cout << "Maximum Columns per Index: " << dbcon_meta->getMaxColumnsInIndex() << endl;

cout << "Maximum Row Size per Table: " << dbcon_meta->getMaxRowSize() << " bytes" << endl;

cout << "\nDatabase schemas: " << endl;

auto_ptr < ResultSet > rs ( dbcon_meta->getSchemas());

cout << "\nTotal number of schemas = " << rs->rowsCount() << endl;

cout << endl;

int row = 1;

while (rs->next()) {

cout << "\t" << row << ". " << rs->getString("TABLE_SCHEM") << endl;

++row;

} // while

cout << endl << endl;

}

/* 獲取結果集信息 */

static void GetResultDataMetaBata(ResultSet *rs)

{

if (rs -> rowsCount() == 0)

{

throw runtime_error("ResultSetMetaData FAILURE - no records in the result set");

}

cout << "ResultSet Metadata" << endl;

cout << "------------------" << endl;

/* The following commented statement won't work with Connector/C++ 1.0.5 and later */

//auto_ptr < ResultSetMetaData > res_meta ( rs -> getMetaData() );

ResultSetMetaData *res_meta = rs -> getMetaData();

int numcols = res_meta -> getColumnCount();

cout << "\nNumber of columns in the result set = " << numcols << endl << endl;

cout.width(20);

cout << "Column Name/Label";

cout.width(20);

cout << "Column Type";

cout.width(20);

cout << "Column Size" << endl;

for (int i = 0; i < numcols; ++i)

{

cout.width(20);

cout << res_meta -> getColumnLabel (i+1);

cout.width(20);

cout << res_meta -> getColumnTypeName (i+1);

cout.width(20);

cout << res_meta -> getColumnDisplaySize (i+1) << endl << endl;

}

cout << "\nColumn \"" << res_meta -> getColumnLabel(1);

cout << "\" belongs to the Table: \"" << res_meta -> getTableName(1);

cout << "\" which belongs to the Schema: \"" << res_meta -> getSchemaName(1) << "\"" << endl << endl;

}

/* 打印結果集中的數據 */

static void RetrieveDataAndPrint(ResultSet *rs, int type, int colidx, string colname)

{

/* retrieve the row count in the result set */

cout << "\nRetrieved " << rs->rowsCount() << " row(s)." << endl;

cout << "\nCityName" << endl;

cout << "--------" << endl;

/* fetch the data : retrieve all the rows in the result set */

while (rs->next())

{

if (type == NUMOFFSET)

{

cout << rs -> getString(colidx) << endl;

} else if (type == COLNAME)

{

cout << rs -> getString(colname) << endl;

} // if-else

} // while

cout << endl;

}

void Demo()

{

Driver *driver;

Connection *con;

Statement *stmt;

ResultSet *res;

PreparedStatement *prep_stmt;

Savepoint *savept;

int updatecount = 0;

/* initiate url, user, password and database variables */

string url(DBHOST);

const string user(USER);

const string password(PASSWORD);

const string database(DATABASE);

try

{

driver = get_driver_instance();

/* create a database connection using the Driver */

con = driver -> connect(url, user, password);

/* alternate syntax using auto_ptr to create the db connection */

//auto_ptr con (driver -> connect(url, user, password));

/* turn off the autocommit */

con -> setAutoCommit(0);

cout << "\nDatabase connection\'s autocommit mode = " << con -> getAutoCommit() << endl;

/* select appropriate database schema */

con -> setSchema(database);

/* retrieve and display the database metadata */

GetDBMetaData(con);

/* create a statement object */

stmt = con -> createStatement();

cout << "Executing the Query: \"SELECT * FROM City\" .." << endl;

/* run a query which returns exactly one result set */

res = stmt -> executeQuery ("SELECT * FROM City");

cout << "Retrieving the result set .." << endl;

/* retrieve the data from the result set and display on stdout */

RetrieveDataAndPrint (res, NUMOFFSET, 1, string("CityName"));

/* retrieve and display the result set metadata */

GetResultDataMetaBata (res);

cout << "Demonstrating Prepared Statements .. " << endl << endl;

/* insert couple of rows of data into City table using Prepared Statements */

prep_stmt = con -> prepareStatement ("INSERT INTO City (CityName) VALUES (?)");

cout << "\tInserting \"London, UK\" into the table, City .." << endl;

prep_stmt -> setString (1, "London, UK");

updatecount = prep_stmt -> executeUpdate();

cout << "\tCreating a save point \"SAVEPT1\" .." << endl;

savept = con -> setSavepoint ("SAVEPT1");

cout << "\tInserting \"Paris, France\" into the table, City .." << endl;

prep_stmt -> setString (1, "Paris, France");

updatecount = prep_stmt -> executeUpdate();

cout << "\tRolling back until the last save point \"SAVEPT1\" .." << endl;

con -> rollback (savept);

con -> releaseSavepoint (savept);

cout << "\tCommitting outstanding updates to the database .." << endl;

con -> commit();

cout << "\nQuerying the City table again .." << endl;

/* re-use result set object */

res = NULL;

res = stmt -> executeQuery ("SELECT * FROM City");

/* retrieve the data from the result set and display on stdout */

RetrieveDataAndPrint(res, COLNAME, 1, string ("CityName"));

cout << "Cleaning up the resources .." << endl;

/* Clean up */

delete res;

delete stmt;

delete prep_stmt;

con -> close();

delete con;

} catch (SQLException &e) {

cout << "ERROR: " << e.what();

cout << " (MySQL error code: " << e.getErrorCode();

cout << ", SQLState: " << e.getSQLState() << ")" << endl;

if (e.getErrorCode() == 1047) {

/*

Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)

Message: Unknown command

*/

cout << "\nYour server does not seem to support Prepared Statements at all. ";

cout << "Perhaps MYSQL < 4.1?" << endl;

}

return;

} catch (std::runtime_error &e) {

cout << "ERROR: " << e.what() << endl;

return;

}

return;

}

建立數據庫連接

sql::Connection代表到數據庫的連接,可以通過sql::Driver來創建。sql::mysql::get_mysql_driver_instance()方法用于獲取sql::Driver,通過調用sql::Driver::connect方法來創建sql::Connection對象。(譯者注:筆者使用的Connector/C++版本與作者使用的版本不一樣,接口方面也有點細微的差別。這里根據筆者使用的最新版本mysql-connector-c++-noinstall-1.0.5-win32來說明。)

下面是get_mysql_driver_instance與connect這兩個方法的簽名:

/* mysql_driver.h */

MySQL_Driver *sql::mysql::get_mysql_driver_instance()

/* mysql_driver.h */

sql::Connection * connect(const std::string& hostName, const std::string& userName, const std::string& password);

sql::Connection * connect(std::map<:string sql::connectpropertyval> & options);

Driver類重載了connect方法,一個接收數據庫地址的url、用戶名和密碼的字符串,后一個接收一個map,map中以key/value的形式包含數據庫地址、用戶名與密碼。使用TCP/IP連接到MySql服務器的url字符串的格式如下:"tcp://[hostname[:port]][/schemaname]"。例如:tcp://127.0.0.1:5555/some_scehma。hostname和端口號是可選的,如果省略,默認是127.0.0.1與3306。如果hostname為"localhost",會被自動轉換為"127.0.0.1"。schemaname也是可選的,如果連接字符串中沒有設置schema,需要在程序中通過Connection::setSchema方法手動設置。

在unix系統上,可以通過UNIX domain socket連接運行在本地的MySQL服務,連接字符串格式為:"unix://path/to/unix_socket_file",例如:unix:///tmp/mysql.sock.

在windows系統上,可以以命名管道的方式連接到運行在本地的MySQL數據庫,連接字符串格式為:"pipe://path/to/the/pipe"。MySQL服務必須啟動允許命名管道連接,可以在啟動MySQL服務器的時候,通過--enable-named-pipe命令行選項來啟動該功能。如果沒有通過--socket=name選項設置命名管道的名稱,系統默認使用MySQL。在windows上,管道的名稱是區別大小寫的。

下面的代碼片斷嘗試連接到本地的MySQL服務器,通過3306端口,用戶名為root,密碼是000000,schema為test.

sql::mysql::MySQL_Driver *driver = 0;

sql::Connection *conn = 0;

try

{

driver = sql::mysql::get_mysql_driver_instance();

conn = driver->connect("tcp://localhost:3306/test", "root", "000000");

cout << "連接成功" << endl;

}

catch (...)

{

cout << "連接失敗" << endl;

}

if (conn != 0)

{

delete conn;

}

也可以通過connection的第二個重載方法連接MySQL。ConnectPropertyVal是union類型,在connection.h中定義。

sql::mysql::MySQL_Driver *driver = 0;

sql::Connection *conn = 0;

std::map<:string connectpropertyval> connProperties;

ConnectPropertyVal tmp;

tmp.str.val = "tcp://127.0.0.1:3306/test";

connProperties[std::string("hostName")] = tmp;

tmp.str.val = "root";

connProperties[std::string("userName")] = tmp;

tmp.str.val = "000000";

connProperties[std::string("password")] = tmp;

try

{

driver = sql::mysql::get_mysql_driver_instance();

conn = driver -> connect(connProperties);

cout << "連接成功" << endl;

}

catch(...)

{

cout << "連接失敗" << endl;

}

if (conn != 0)

{

delete conn;

}

上面的連接字符串可以將協議與路徑分開寫(譯者注:C++會把兩個連在一起的字符串合并成一個字符串),如:mp.str.val = "unix://" "/tmp/mysql.sock"

當建立與服務器之間的連接后,通過Connection::setSessionVariable方法可以設置像sql_mode這樣的選項。

C++細節注意點

像Connection這樣的對象,必須在用完之后,顯式的delete,例如:

sql::Connection *conn = driver -> connect("tcp://127.0.0.1:3306", "root", "000000");

// do something

delete conn

使用使用auto_ptr來維護連接對象的清理, 如:

use namespace std;

use namespace sql;

auto_ptr < Connection > con ( driver -> connect("tcp://127.0.0.1:3306", "root", "000000") );

獲取Statement對象

Statement對象用于向MySQL服務器發送SQL語句。該對象可以通過調用Connection::createStatement方法獲得。Statement向MySQL發送一個靜態的SQL語句,然后從MySQL獲取操作的結果,我們無法向它提供sql參數。如果要向它傳遞參數,可以使用PreparedStatemenet類。如果相同的SQL語句(只SQL參數不同)要被執行多次,建議使用PreparedStatement類。

Connection::createStatement的簽名如下(關于Connection類所提供的方法列表,可以查看connection.h頭文件):

/* connection.h */

Statement* Connection::createStatement();

下面的的代碼段通過調用Connection對象的createStatemenet來獲取一個Statement對象:

Connection *conn; // Connection對象的引用

Statement *stat;

Statement stat = conn -> createStatement();

執行SQL語句

在執行SQL語句之前應該通過Connection對象的setSchema方法設置相應的Schema(如果沒有在數據庫地址URL中指定schema)。

Statement::executeQuery用于執行一個Select語句,它返回ResultSet對象。Statement::executeUpdate方法主要用于執行INSERT, UPDATE, DELETE語句(executeUpdate可以執行所有的SQL語句,如DDL語句,像創建數據表。),該方法返回受影響記錄的條數。

如果你不清楚要執行的是像select這樣的查詢語句還是像update/insert/delete這樣的操作語句,可以使用execute方法。對于查詢語句,execute()返回True,然后通過getResultSet方法獲取查詢的結果;對于操作語句,它返回False,通過getUpdateCount方法獲取受影響記錄的數量。

在一些特殊的情況下,單條SQL語句(如執行存儲過程),可能會返回多個結果集 和/或 受影響的記錄數量。如果你不想忽略這些結果,通過getResultSet或getUpdateCount方法第一個結果后,再通過getMoreResults()來獲取其他的結果集。

下面是這些方法的簽名,可以在statement.h頭文件中查閱Statement的完整方法列表。

/* connection.h */

void Connection::setSchema(const std::string& catalog);

/* statement.h */

ResultSet* Statement::executeQuery (const std::string& sql);

int Statement::executeUpdate (const std::string& sql);

bool Statement::execute (const std::string& sql);

ResultSet* Statement::getResultSet();

uint64_t Statement::getUpdateCount();

這些方法出錯時都會拋出SQLException異常,所以在你的代碼中應該使用try...catch語句塊來捕獲這些異常。

現在回顧上面那個完全的例子,你會發現獲取City表的所有記錄是如此的簡單:

Statement *stmt;

ResultSet *res;

res = stmt -> executeQuery ("SELECT * FROM City");

executeQuery方法返回ResultSet對象,它包含了查詢的結果。在以下情況下,executeQuery會拋出SQLException異常:數據庫在執行查詢時出錯;在一個關閉的Statement對象上調用executeQuery;給出的SQL語句返回的不是一個簡單的結果集;

上面的代碼可以用Statement::execute()重寫:

bool retvalue = stmt -> execute ("SELECT * FROM City");

if (retvalue)

{

res = stmt -> getResultSet();

}

else

{

...

}

execute()返回True表示操作的結果是一個ResultSet對象,否則結果是受影響記錄的數量或沒有結果。當返回True時,通過getResultSet方法獲取結果集,在返回False的情況下調用getResultSet方法,將返回NULL。

當數據庫在執行時發生錯誤或者在一個已關閉的Statement對象上執行execute與getResultSet方法,都會拋出SQLException異常。

如果要往數據庫里添加一條新的記錄,可以像下面的例子一樣簡單的調用executeUpdate方法:

int updateCount = stmt -> executeUpdate ("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");

如果executeUpdate執行的是像INSERT, UPDATE或DELETE這樣的數據操作語句(DML),它返回受影響的記錄的數量;如果執行的是數據定義語句(DDL),它返回0。在數據庫操作失敗,或者在一個已經關閉的Statement上調用該方法,或者給出的SQL語句是一個查詢語句(會返回結果集),該方法會拋出SQLException異常。

下面的代碼使用execute和getUpdateCount方法來生寫上面的例子:

int updateCount = 0;

bool retstatus = stat->execute("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");

if (!retstatus)

{

updateCount = stat->getUpdateCount();

}

else

{

...

}

從ResultData中獲取數據

上面的段落介紹了執行SQL查詢的方法:executeQuery和execute,用于獲取ResultSet對象。我們可以通過ResultSet訪問查詢的結果。每一個ResultSet都包含一個游標(cursor),它指向數據集中的當前記錄行。ResultSet中排列的記錄是有序的(譯者注:只能按順序一條一條獲取,不能跳躍式獲取)。(但)在同一行中,列值的訪問卻是隨意的:可以通過列的位置或者名稱。通過列的名稱訪問列值讓代碼更清晰,而通過位置訪問列值則更高效。

列的名稱通過SQL語句的AS子名設定,如果SQL語句中沒有使用AS子名,列的名稱默認為數據表中對應的列名。例如對于"SELECT CityName AS CN FROM City",CN就是結果集中列的名稱。

在ResultSet中的數據,可以通過getXX系列方法來獲取,例如:getString(), getInt(),"XX"取決于數據的類型。next()與previous()使游標移到結果集中的下一條或上一條記錄。

Statement執行SQL語句返回ResultSet對象后,ResultSet就變成一個獨立的對象,與原先的Statement再也沒有聯系,即使Statement對象關閉,重新執行其他sql語句,或者獲取多個結果集中的下一個。ResultSet將一直有效,除非顯式或隱式地將其關閉。

在撰寫本文時,對于Statement對象,MySQL Connector/C++總是返回緩存結果,這些結果在客戶端緩存。不管結果集數據量大小,MySQLConnector/C++ Driver總是獲取所有的數據。希望以后的版本中,Statement對象能夠返回緩存和非緩存的結果集。

下面是數據獲取方法的簽名,可以在resultset.h頭文件中查看所有ResultSet類支持的方法。

/* resultset.h */

size_t ResultSet::rowsCount() const;

void ResultSet::close();

bool ResultSet::next();

bool ResultSet::previous();

bool ResultSet::last();

bool ResultSet::first();

void ResultSet::afterLast();

void ResultSet::beforeFirst();

bool ResultSet::isAfterLast() const;

bool ResultSet::isBeforeFirst()const;

bool ResultSet::isClosed() const;

bool ResultSet::isNull(uint32_t columnIndex) const;

bool ResultSet::isNull(const std::string& columnLabel) const;

bool ResultSet::wasNull() const;

std::string ResultSet::getString(uint32_t columnIndex) const;

std::string ResultSet::getString(const std::string& columnLabel) const;

int32_t ResultSet::getInt(uint32_t columnIndex) const;

int32_t ResultSet::getInt(const std::string& columnLabel) const;

在下面的簡單示例中,查詢語句"SELECT * FROM City"返回的ResultSet中只包含一列:CityName,數據類型為String,對應MySQL中的VARCHAR類型。這個例子通過next方法循環從結果集中獲取CityName值,并顯示在控制臺上:

while (res -> next())

{

cout << rs -> getString("CityName") << endl;

}

也可以通過位置來獲取列值(位置從1開始而非從0開始),下面的代碼產生相同的結果:

while (res -> next())

{

cout << rs -> getString(1) << endl;

}

如果數據庫中該字段的值為NULL,getString將返回一個空的字符串。Result::isNull用于判斷指定列在數據庫中的值是否為NULL。Result::wasNULL()用于判斷最近讀取的列的值是否為空。

下面的例子演示了通過cursor(游標)倒序讀取結果集中的數據:

/* Move the cursor to the end of the ResultSet object, just after the last row */

res -> afterLast();

if (!res -> isAfterLast())

{

throw runtime_error("Error: Cursor position should be at the end of the result set after the last row.");

}

/* fetch the data : retrieve all the rows in the result set */

while (res -> previous())

{

cout << rs->getString("CityName") << endl;

}

getString方法在以下情況下會拋出SQLException異常:指定列名或位置不存在;數據庫在執行操作時失敗;在一個關閉的cursor上執行調用該方法。

未完待續!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539693.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539693.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539693.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

14-項目開發總結報告(GB8567——88)

項目開發總結報告&#xff08;GB8567——88&#xff09;1引言1.1編寫目的說明編寫這份項目開發總結報告的目的&#xff0c;指出預期的閱讀范圍。1.2背景說明&#xff1a;a&#xff0e; 本項目的名稱和所開發出來的軟件系統的名稱&#xff1b;b&#xff0e; 此軟件的任務提出者、…

Oracle 并行查詢

所謂并行執行&#xff0c;是指能夠將一個大型串行任務&#xff08;任何DML&#xff0c;一般的DDL&#xff09;物理的劃分為叫多個小的部分&#xff0c;這些較小的部分可以同時得到處理。 何時使用并行執行: 1、必須有一個非常大的任務 2、必須有充足的資源&#xff08;CPU,I…

python中求二維數組元素之和_python二維列表求解所有元素之和

相信很多初學小伙伴都會遇到二維列表求解所有元素之和問題,下面給出兩種兩種常見的求和方法。 方法1: 思想:遍歷整個二維列表元素,然后將所有元素加起來 1 def Sum_matrix(matrix): 2 sum=0 3 for i in range(len(matrix)): 4 for j in range(len(matrix[i])): 5 sum+=matr…

maven 國內私服

2019獨角獸企業重金招聘Python工程師標準>>> <repositories> <repository> <id>aliyun-cache</id> <name>aliyun-cache</name> <url>http://maven.aliyun.com/nexus/content/groups/public&…

mysql添加約束之前不滿足_MySQL:添加約束(如果不存在)

小編典典有趣的問題。您可能需要在調用CREATE TABLE語句之前禁用外鍵&#xff0c;然后再啟用它們。這將允許您直接在CREATE TABLEDDL中定義外鍵&#xff1a;例&#xff1a;SET FOREIGN_KEY_CHECKS 0;Query OK, 0 rows affected (0.00 sec)CREATE TABLE IF NOT EXISTS rabbits …

oracle函數trunc的使用

原文&#xff1a;http://blog.csdn.net/eleven204/article/details/6712538 -------------------------------------- 1、日期比較時精確到日&#xff0c;可以使用 TRUNC(sysdate,dd)函數。 函數支持格式有&#xff1a;yyyy MM dd hh Mi&#xff0c;沒有精確到 秒 可以用 se…

Mycat快速入門

1.Mycat介紹 Mycat 是一個開源的分布式數據庫系統&#xff0c;是一個實現了 MySQL 協議的的Server&#xff0c;前端用戶可以把它看作是一個數據庫代理&#xff0c;用 MySQL 客戶端工具和命令行訪問&#xff0c;而其后端可以用MySQL 原生&#xff08;Native&#xff09;協議與多…

python字符串常量有什么區別_Python經典面試題:is與==的區別

is用于判斷兩個對象是否為同一個對象&#xff0c;具體來說是兩個對象在內存中的位置是否相同。python為了提高效率&#xff0c;節省內存&#xff0c;在實現上大量使用了緩沖池技術和字符串intern技術。整數和字符串是不可變對象&#xff0c;也就意味著可以用來共享&#xff0c;…

left join、right join、inner join的區別

left join(左聯接) 返回包括左表中的所有記錄和右表中聯結字段相等的記錄 right join(右聯接) 返回包括右表中的所有記錄和左表中聯結字段相等的記錄 inner join(等值連接) 只返回兩個表中聯結字段相等的行 舉例如下&#xff1a; ----------------------------------------…

Javascript Proxy對象 簡介

Javascript Proxy對象 簡介 本文轉載自&#xff1a;眾成翻譯 譯者&#xff1a;eJayYoung 鏈接&#xff1a;http://www.zcfy.cc/article/4755 原文&#xff1a;https://blog.campvanilla.com/advanced-guide-javascript-proxy-objects-introduction-301c0fce9432 Javascript …

App架構經驗總結

原文地址&#xff1a;http://www.iteye.com/news/31472-------------------------------------------------------------架構因人而異&#xff0c;不同的架構師大多會有不同的看法&#xff1b;架構也因項目而異&#xff0c;不同的項目需求不同&#xff0c;相應的架構也會不同。…

python數字排序 循環_【python-leetcode448-循環排序】找到所有數組中消失的數字

問題描述&#xff1a;給定一個范圍在 1 ≤ a[i] ≤ n ( n 數組大小 ) 的 整型數組&#xff0c;數組中的元素一些出現了兩次&#xff0c;另一些只出現一次。找到所有在 [1, n] 范圍之間沒有出現在數組中的數字。您能在不使用額外空間且時間復雜度為O(n)的情況下完成這個任務嗎…

saiku+kettle整合(六)olap操作

title: saikukettle整合&#xff08;六&#xff09;olap操作 tags: categories: saiku date: 2016-08-25 18:18:54 使用saiku可以對應使用相關olap操作 OLAP的基本操作 我們已經知道OLAP的操作是以查詢——也就是數據庫的SELECT操作為主&#xff0c;但是查詢可以很復雜&#xf…

攜程Docker實踐

原文地址&#xff1a;http://www.iteye.com/news/31468 請點擊原文閱讀 ---------------------以下是原文---------------------- 從去年底開始&#xff0c;攜程開始計劃把Docker引入到攜程的云平臺&#xff0c;這是系統研發部一部分的工作任務&#xff0c;攜程系統研…

mysql全文索引thinkphp_ThinkPHP5 使用迅搜 (XunSearch) 實現全文檢索實例指導

前期準備入坑了一天&#xff0c;折騰的無語&#xff0c;個人觀點&#xff1a;【文檔太差&#xff0c;適合學習思路&#xff0c;不建議入坑】背景最近在整理全文檢索解決方案注意到 xunsearch 的評價很高&#xff0c;在此記錄一番場景描述此處作為對 xunsearch 的初次使用&#…

為何有些程序員總是想要“干掉”產品經理?

好了&#xff0c;我準備去和產品經理做斗爭去了&#xff0c;請祝我好運吧&#xff01;小編花了大量時間收集了很多干貨編程學習資源&#xff0c;其中資源包括 算法&#xff0c;大數據&#xff0c;人工智能&#xff0c;Python&#xff0c;Android&#xff0c;iOS&#xff0c;Jav…

多個left join 產生多個結果

select a.*,to_char(To_date(20160403000000, yyyyMMddhh24miss),yyyy/mm/dd) as omc_start_time,to_char(To_date(20160404000000, yyyyMMddhh24miss),yyyy/mm/dd) as omc_end_time,ROUND(sc."切換成功率",2) AS "OMC-源小區切換成功率%",ROUND(sc."…

查看進程占用,并kill掉

今天發現8899端口被占&#xff0c;服務器啟動失敗&#xff0c;用了下面的命令解決。 [rootltesqm Toolbox]# netstat -tunlp |grep 8899 tcp 0 0 :::8899 :::* LISTEN 28279/java [rootltesqm Toolbox]…

Spark算子篇 --Spark算子之combineByKey詳解

一。概念 rdd.combineByKey(lambda x:"%d_" %x, lambda a,b:"%s%s" %(a,b), lambda a,b:"%s$%s" %(a,b))三個參數&#xff08;都是函數&#xff09;第一個參數&#xff1a;給定一個初始值&#xff0c;用函數生成初始值。第二個參數&#xff1a;c…

mysql proxy 主從_【MYSQL知識必知必會】MySQL主從復制讀寫分離(基于mysql-proxy實現)...

MySQL主從復制讀寫分離(基于mysql-proxy實現)http://mirror.bit.edu.cn/mysql/Downloads/MySQL-Proxy/mysql-proxy-0.8.4-linux-glibc2.3-x86-64bit.tar.gz解壓tar zxvf mysql-proxy-0.8.4-linux-glibc2.3-x86-64bit.tar.gz創建mysql-proxy帳號并授權分別在主從數據庫中創建mys…