各位,
我經常需要來自不同來源的數據並將它們組合起來。 由於某些查詢可能需要很多時間,我編寫了一個腳本,在後台啟動多個查詢並在最後合併資料。 然而,要找到觸發器、何時完成所有查詢以及何時開始處理結果並不是那麼容易。 在下面的腳本中,我測試了兩種方法(透過「OnRunComplete」設定標誌並測試結果表是否存在)。 它們相當有效,但我認為可能有更好的方法。
一個問題是,如果其中一個查詢沒有提供表,則循環將無限運行。 另一個問題是,腳本並不能真正控制查詢是否仍處於活動狀態。
該腳本目前設定為調試模式,無需資料庫連接即可測試此行為。
有什麼改進的想法嗎? 謝謝,BR
// Purpose:
// Start two database Queries (from different sources) in parallel and in background
// Wait for queries to finish
// and combine result
// JMP 15.0 Win10
//
// Details:
// After both queries are started in background
// a loop is started, that queries when both tables are existing
// In a previous version I worked with setting a flag ("OnRunComplete( B_QUERY_FINISHED = 1 )")
//
// Problem:
// A better solution would be to test, whether DB query is still running, but how?
// If the database query ends unexpectedly (by passing no table), the loop runs infinetely
Names Default To Here( 1 );
Clear Log();
// debug_mode: 0 - query from database / 1 - make table
// for database query the connectionstring must be correct
debug_mode = 1;
A_QUERY_FINISHED = 0;
B_QUERY_FINISHED = 0;
A_NAME = "A_Table";
B_NAME = "B_Table";
// new function to check whether background query is finished (= table does exists)
table_exists = Function( {table_name},
Names Default To Here( 1 );
table_lst = Get Data Table List();
table_name_lst = {};
For( i = 1, i <= N Items( table_lst ), i++,
Insert Into( table_name_lst, table_lst[i] << get name() )
);
Return( If( Contains( table_name_lst, table_name ) > 0, 1, 0 ) );
);
If( table_exists( A_NAME ) | table_exists( B_NAME ) ,
Throw( eval insert ("^A_NAME^ or ^B_NAME^ open! Please close " ))
);
// Define query
sql_str = "Select * from dual";
A_sql_str = sql_str;
B_sql_str = Substitute( sql_str, "A_scheme", "B_scheme" );
// Database query expression in backgroud
nsqlq_A_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=XXX;DBQ=YYY;" ), QueryName( A_Name ), CustomSQL( A_sql_str ) ) <<
Run Background( OnRunComplete( A_QUERY_FINISHED = 1 ) )
);
nsqlq_B_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=ZZZ;DBQ=AAA;" ), QueryName( B_Name ), CustomSQL( B_sql_str ) ) <<
Run Background( OnRunComplete( B_QUERY_FINISHED = 1 ) )
);
// Create table expression for Debugging
A_expr = Expr(
New Table( "A_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
B_expr = Expr(
New Table( "B_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
// start queries only in case of no debug_mode
If( debug_mode == 0,
Eval( nsqlq_A_expr );
Eval( nsqlq_B_expr );
);
start_time = Tick Seconds();
timestep = 1;
While( (table_exists( A_NAME ) & table_exists( B_NAME )) != 1,
Wait( timestep );
time_running = Round( Tick Seconds() - start_time, 0 );
Print( "waiting " || Char( time_running ) );
Show( table_exists( A_NAME ) );
Show( table_exists( B_NAME ) );
// For debugging only: create Table A after 5 seconds and Table B after 10 seconds
If( debug_mode == 1,
If( time_running > 5 & !table_exists( A_NAME ),
Eval( A_expr )
);
If( time_running > 10 & !table_exists( B_NAME ),
Eval( B_expr )
);
);
);
Wait( 1 );
Print( "Queries Finished" );
end_time = Tick Seconds();
Print( "Duration: " || Char( Round( end_time - start_time ) ) );
// concatenate
Try( Data Table( A_Name ) << Concatenate( Data Table( B_Name ), Append to first table ), Throw( Print( "Concatenate error" ) ) );
// Close( Data Table( B_Name ), nosave );
Data Table( A_Name )<< set name("Result Table");
Print( "Concatenating finished, script end " );我不相信我遇到過同樣的問題,如果您仍然遇到問題,您可以發布帶有錯誤的日誌輸出嗎?或者如果您可以修復它,您可以讓我知道如何更新範例腳本嗎?
首選項中有一個 ODBC 設定導致了我類似的錯誤行為。 如果選取「如果可能,請在背景執行查詢」選項,請取消選取它並再次嘗試您的腳本。 我認為這樣做需要在速度和穩定性之間進行權衡,但如果您還沒有嘗試過,那麼值得嘗試。

謝謝@ih對於你的解決方案,它很好並且編程良好,所以我會嘗試使用它。
在第一次測試中,我仍然看到一些計時問題(我想),因為參考(尚未)有效。
在語句“onRunComplete”中引入等待幾秒鐘然後可以工作,但不是解決方案。
我想這就是為什麼我之前決定在引用可用表之前查詢它。 我將進一步測試它。