在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們問題
您希望在後台運行查詢,以便用戶界面不會凍結,或者您希望同時運行多個查詢,然後合併結果。 有時,很難將您需要的所有功能放入後台查詢的“運行時完成”腳本中。
解決方案
每個查詢將結果保存在所有腳本都可以訪問的新命名空間中(查詢和原始腳本)。原始腳本在繼續之前會不斷檢查結果。
//Example script which runs queries in the background and references their results
//once finished.
Names default to here(1);
// Namespace to share data between background query and this script
ns = new namespace( "queries" );
// Flags which the background query will set to 1 when the background query is complete
ns:query1isdone = 0;
ns:query2isdone = 0;
// Open a window to display results
win = New window("Query Status", show menu(0), show toolbars(0),
text box("Status of queries:"),
tb = tablebox( string col box( "Query" , { "Query 1", "Query 2" } ),
string col box( "Status", { "Not Started", "Not Started" } ) ),
tbStatus = text box("Starting queries.")
);
wait(0); //make sure window shows up
// Define and start background queries
// First Query
sql_query1 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query1 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt1 = queryResult;
ns:query1isdone = 1;
) );
// Second Query
sql_query2 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query2 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
// Every second check if the query is done (timeout after 10 seconds)
i=0;
allqueriesdone = 0;
starttime = tick seconds();
while( ( i < 10 ) & allqueriesdone == 0 ,
i++;
wait(1);
if( ns:query1isdone == 1,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Complete"} );,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Still Running"} );
);
if( ns:query2isdone == 1,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Complete"} );,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Still Running"} );
);
if( (ns:query1isdone == 1 ) & (ns:query2isdone == 1 ), allqueriesdone = 1 ); //indicate that everything finished
tbStatus << Set Text( "Queries are running, " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds elapsed." );
win << bring window to front;
);
// Show an error if any queries didn't finish
if( allqueriesdone == 0,
tbStatus << Set Text("Error, a query didn't finish and is still running!"),
tbStatus << Set Text("Queries finished after " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds.");
//win << Close Window; //could close window here
);
// Now reference the data tables
show( ns:dt1 );
show( ns:dt2 );您希望在後台運行查詢,但需要與結果進行交互。此方法允許在與結果交互之前完成多個後台查詢。
公用事業回复:在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們你好@馬克代頓,
感謝您深入研究這一點,因為您指出了我剛剛更正的腳本的不足之處。 我在 OnRunComplete 腳本中沒有將名稱默認設置為此處(1),因此它沒有完全按照我的計劃工作。這是更新前後命名空間的描述我只是製成:
概述
注意命名空間“查詢”是如何的已創建在父腳本中,然後引用的在 OnRunComplete 腳本中。變量 ns 本身僅用於引用命名空間“queries”。例如,在新的腳本窗口中您可以運行:
Names default to here(1);
ns = New Namespace("queries");
ns:a = 1
第二個腳本窗口可以通過調用獲取 a 的值:
Names default to here(1);
Show(Namespace("queries"):a);
但您無法輕鬆地在另一個窗口中訪問 ns。 但是,您可以在另一個窗口中定義一個新變量,然後以類似的方式訪問 a:
Names default to here(1);
nsreference = Namespace("queries");
Show(nsreference);
或者,為了使代碼更易於閱讀,您可以在兩個窗口中使用相同的變量名稱。變量本身是不同的,因為它們是在不同的命名空間中定義的,但它們引用相同的東西,因此您可以以相同的方式使用它們。
Names default to here(1);
ns = Namespace("queries");
Show(ns:a);
這就是上面示例腳本中變量的使用方式:在每個引用命名空間“queries”的命名空間中創建一個名為“ns”的變量,從而更容易在這些腳本之間共享值。
變更前- 如果不啟動名稱默認為此處的每個 OnRunComplete 腳本(1),這將如何工作:
查看更多...
變更後- 腳本現在如何工作
該腳本使用了四個命名空間:
- 父腳本窗口的here命名空間
- 第一個查詢的 OnRunComplete 腳本的此處命名空間
- 第二個查詢的 OnRunComplete 腳本的here命名空間
- 名為“queries”的命名空間,由父腳本和兩個 OnRunComplete 腳本引用
父腳本中的變量 ns 在here命名空間中定義為參考查詢命名空間,使用 New Namespace() 創建。這意味著只有腳本窗口可以訪問 ns,但該 JMP 實例中的其他任何內容都可以引用 ns 引用的查詢命名空間中保存的任何內容。
OnRunComplete 腳本在新環境中打開,並且無權訪問父腳本的此處命名空間。因此,在該腳本的 here 命名空間中定義了一個也稱為 ns 的新變量,並將其設置為使用 Namespace() 引用“查詢”命名空間。每個運行完成的腳本都會在其自己的此處命名空間中創建名為 ns 的自己的變量,但隨後每個變量都將被設置為引用相同的“查詢”命名空間。
回复:在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們首先,感謝您提供這個腳本。 使用命名空間、編寫 SQL 查詢腳本、測試是否完成,提供狀態反饋、管理結果;該腳本將大量教學內容打包到幾行 JSL 中。大部分內容我都能聽懂,但是我沒有太多定義和使用命名空間的經驗,所以我有一個問題:
在腳本的第二行中,納秒是定義為:
ns = new namespace( "queries" );
那麼看來納秒在 Run Background() 語句中重新定義:
sql_query2 << Run Background( OnRunComplete(
ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
sql_query1 & 2 中的命名空間是否與腳本開頭定義的命名空間相同(看起來必須如此),或者它是查詢語句本地的命名空間,因為名稱默認為此處(1)開頭的聲明? 為什麼納秒需要在 Run Background() 語句中定義嗎?
再次感謝您提供了一段簡單、清晰、漂亮的代碼。
回复:在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們儘管如此,還是有一些很好的代碼可以在緊要關頭參考。 
回复:在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們你好@Byron_JMP ,
我同意,如果目標是檢查交互式運行的查詢的狀態,那麼用戶應該只看查詢生成器。此狀態窗口旨在演示用戶通過簡單的 Web 搜索難以找到的查詢的處理部分,例如在腳本完成後引用腳本中的結果。 老實說,我記得很難想出一個最小的例子。我確信那裡有更好的用例......
回复:在後台運行查詢,等待它們完成,並在剩餘的 JSL 腳本中引用它們這聽起來是一個非常有趣的項目想法。
我只是想指出,在查詢生成器中,有一個進度選項卡,我可以在其中查看正在運行的查詢數量及其進度。 也許這將是一種編寫查詢構建器平台腳本來顯示此信息而不是嘗試從頭開始獲取它的方法?