は、だから、私はスペア時間に数週間、今私のこのペットプロジェクトに取り組んできたと私はこだわって問題全体で起きています。私はそれを見て、問題をGoogleで調べて、私の特定の問題に本当に関係するものは何も見つけ出していません。カーソル状態、C++同時実行性とSQLサーバー
私は、ローカルのSQL Serverインスタンスに接続するために、ODBCドライバを使用する(私はCでマルチスレッドに非常に新しいです++)マルチスレッドを実行していますよ。 接続が正常に動作して上のすべてのものを使用しているメインスレッドは大丈夫です。しかし、私は複数のスレッドを使用して起動したときに(上記のように、それはたわごとのように見える - 私は試行錯誤によって学んでいる)私はC++ concurrenctyと私は、ストアドプロシージャとしなければならないと思うのエラーメッセージを取得していますSQLサーバー上で実行されます。 show_errorによって表示される
エラーメッセージ:
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_addHistorical] Script Date: 30/03/2016 10:16:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_addHistorical]
@Symbol nchar(10),@Date datetime,
@Open decimal(12,2),@Close decimal(12,2),@MinPrice decimal(12,2),
@MaxPrice decimal(12,2),@Volume int
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRANSACTION
MERGE HistoricalStock WITH (UPDLOCK) AS myTarget
USING (SELECT @Symbol AS Symbol,
@Date AS Date, @Open AS [Open], @Close AS [Close],
@MinPrice AS MinPrice, @MaxPrice AS MaxPrice,@Volume AS Volume) AS mySource
ON mySource.Symbol = myTarget.Symbol AND mySource.Date = myTarget.Date
WHEN MATCHED
THEN UPDATE
SET [Open] = mySource.[Open], [Close] = mySource.[Close],
MinPrice = mySource.MinPrice, MaxPrice = mySource.MaxPrice, Volume = mySource.Volume
WHEN NOT MATCHED
THEN
INSERT(Symbol,Date,[Open],[Close],MinPrice,MaxPrice,Volume)
VALUES(@Symbol,@Date,@Open,@Close,@MinPrice,@MaxPrice,@Volume);
COMMIT
データベースコネクタとくだらないスレッドである:
#include "stdafx.h"
#include "database_con.h"
////////////////////////////////////////////////////////////////////////
// Show errors from the SQLHANDLE
void database_con::show_error(unsigned int handletype, const SQLHANDLE& handle)
{
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL))
wcout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl;
}
std::wstring database_con::StringToWString(const std::string& s)
{
std::wstring temp(s.length(), L' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp;
}
////////////////////////////////////////////////////////////////////////
// Builds the stored procedure query.
std::wstring database_con::buildQuery(vector<std::wstring> input, string symbol)
{
std::wstringstream builder;
builder << L"EXEC sp_addHistorical " << "@Symbol='" << L"" << StringToWString(symbol) << "'," <<
"@Date='" << (wstring)L"" << input.at(0) << "'," <<
"@Open=" << (wstring)L"" << input.at(1) << "," <<
"@Close=" << (wstring)L"" << input.at(2) << "," <<
"@MaxPrice=" << (wstring)L"" << input.at(3) << "," <<
"@MinPrice=" << (wstring)L"" << input.at(4) << "," <<
"@Volume=" << (wstring)L"" << input.at(5) << ";";
return builder.str();
}
void database_con::executeQuery(wstring query) {
if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(query.c_str()), SQL_NTS)) {
std::cout << "Execute error " << std::endl;
show_error(SQL_HANDLE_STMT, stmt);
std::wcout << L"Unsuccessful Query: " << query << std::endl;
}
// Close Cursor before next iteration starts:
SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE);
if (!SQL_SUCCEEDED(closeCursRet))
{
show_error(SQL_HANDLE_STMT, stmt);
// maybe add some handling for the case that closing failed.
}
}
////////////////////////////////////////////////////////////////////////
// Constructs a database connector object with the historical data and its symbol
database_con::database_con(std::vector<std::vector<std::wstring>> historical, string symbol){
/*
Set up the handlers
*/
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN */
SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};SERVER=ERA-PC-STUART\\JBK_DB;DATABASE=master;UID=geo;PWD=kalle123;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
/* Check for success */
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))
{
show_error(SQL_HANDLE_DBC, dbc);
std::cout << "Failed to connect";
}
std::cout << "Building and executing the query" << std::endl;
for (_mVecHistIter = historical.begin();
_mVecHistIter != historical.end();
_mVecHistIter+5) {
std::thread t(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
std::thread t2(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
std::thread t3(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
std::thread t4(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
std::thread t5(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
t.join();
t2.join();
t3.join();
t4.join();
t5.join();
//executeQuery(buildQuery(*_mVecHistIter, symbol));
}
/*_mSymbol = symbol;
std::wstringstream stream(StringToWString(historical));
std::wstring line;
int row = 0;
while (std::getline(stream, line)) {
if (row > 0) {
vector<wstring> vHistorical = parseData(L"" + line, ',');
std::wstring SQL = buildQuery(vHistorical, _mSymbol);
if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(SQL.c_str()), SQL_NTS)) {
std::cout << "Execute error " << std::endl;
show_error(SQL_HANDLE_STMT, stmt);
std::wcout << L"Unsuccessful Query: " << SQL << std::endl;
}
// Close Cursor before next iteration starts:
SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE);
if (!SQL_SUCCEEDED(closeCursRet))
{
show_error(SQL_HANDLE_STMT, stmt);
// maybe add some handling for the case that closing failed.
}
}
row++;
}*/
std::cout << "Query " << _mSymbol << " ready" << std::endl;
}
database_con::~database_con() {
std::cout << "The database object has been deleted" << std::endl;
}