Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufProblem
Sie möchten eine Abfrage im Hintergrund ausführen, damit die Benutzeroberfläche nicht einfriert, oder Sie möchten mehrere Abfragen gleichzeitig ausführen und dann die Ergebnisse kombinieren. Manchmal ist es schwierig, alle benötigten Funktionen in das „On Run Complete“-Skript der Hintergrundabfragen zu integrieren.
Lösung
Jede Abfrage speichert Ergebnisse in einem neuen Namespace, auf den alle Skripte zugreifen können (Abfragen und das ursprüngliche Skript).Das ursprüngliche Skript prüft ständig, ob Ergebnisse vorliegen, bevor es fortfährt.
//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 );Sie möchten Abfragen im Hintergrund ausführen, müssen aber mit den Ergebnissen interagieren.Mit dieser Methode können mehrere Hintergrundabfragen abgeschlossen werden, bevor mit den Ergebnissen interagiert wird.
DienstprogrammeBetreff: Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufHallo @MarkDayton ,
Vielen Dank, dass Sie sich damit befasst haben, da Sie auf einen Mangel im Skript hingewiesen haben, den ich gerade korrigiert habe. Ich hatte in den OnRunComplete-Skripten nicht die Standardeinstellung „Names“ auf „hier(1)“ festgelegt, sodass es nicht genau so funktionierte, wie ich es geplant hatte.Hier finden Sie eine Beschreibung der Namespaces vor und nach dem Update I Nur gemacht:
Überblick
Beachten Sie, wie der Namespace „Abfragen“ ist erstellt im übergeordneten Skript und dann verwiesen in den OnRunComplete-Skripten.Die Variable ns selbst wird nur zur Referenzierung des Namensraums „Abfragen“ verwendet.In einem neuen Skriptfenster könnten Sie beispielsweise Folgendes ausführen:
Names default to here(1);
ns = New Namespace("queries");
ns:a = 1
und ein zweites Skriptfenster könnte den Wert von a erhalten, indem es Folgendes aufruft:
Names default to here(1);
Show(Namespace("queries"):a);
Sie können jedoch im anderen Fenster nicht einfach auf ns zugreifen. Sie können jedoch im anderen Fenster eine neue Variable definieren und dann auf ähnliche Weise auf eine Variable zugreifen:
Names default to here(1);
nsreference = Namespace("queries");
Show(nsreference);
Um den Code leichter lesbar zu machen, können Sie auch in beiden Fenstern denselben Variablennamen verwenden.Die Variablen selbst sind unterschiedlich, da sie in unterschiedlichen Namespaces definiert sind, aber sie verweisen auf dasselbe, sodass Sie sie auf die gleiche Weise verwenden können.
Names default to here(1);
ns = Namespace("queries");
Show(ns:a);
So werden die Variablen im obigen Beispielskript verwendet: In jedem hier genannten Namespace wird eine Variable namens „ns“ erstellt, die auf die benannten Namespace-„Abfragen“ verweist, wodurch es einfacher wird, Werte zwischen diesen Skripten auszutauschen.
Vor dem Wechsel – wie dies funktionieren würde, ohne jedes OnRunComplete-Skript mit den standardmäßigen Namen hier(1) zu starten:
Mehr sehen...
Nach der veränderung - wie das Skript jetzt funktioniert
Das Skript verwendet vier Namespaces:
- Der hier-Namespace für das übergeordnete Skriptfenster
- Der hier-Namespace für das OnRunComplete-Skript der ersten Abfrage
- Der Namespace hier für das OnRunComplete-Skript der zweiten Abfrage
- Der Namespace mit dem Namen „queries“, auf den sowohl das übergeordnete Skript als auch die beiden OnRunComplete-Skripts verweisen
Die Variable ns im übergeordneten Skript ist im Here-Namensraum to definiert Referenz der Abfrage-Namespace, der mit New Namespace() erstellt wird.Das bedeutet, dass nur das Skriptfenster Zugriff auf ns hat, aber alles andere in dieser Instanz von JMP kann auf alles verweisen, was im Abfrage-Namespace gespeichert ist, auf den ns verweist.
Die OnRunComplete-Skripts werden in einer neuen Umgebung geöffnet und haben keinen Zugriff auf den Here-Namespace des übergeordneten Skripts.Daher wird im Here-Namespace dieses Skripts eine neue Variable definiert, die auch „ns“ heißt, und mithilfe von Namespace() auf den Namespace „queries“ verweisen.Jedes ausgeführte vollständige Skript erstellt eine eigene Variable mit dem Namen „ns“ in seinem eigenen Here-Namespace, aber dann wird jede dieser Variablen so eingestellt, dass sie auf denselben „Abfragen“-Namespace verweist.
Betreff: Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufZunächst einmal vielen Dank für dieses Skript. Verwendung von Namespaces, Skripterstellung für SQL-Abfragen, Testen, ob sie fertig sind, Bereitstellung von Statusrückmeldungen, Verwaltung der Ergebnisse; Dieses Skript packt viele Lehrinhalte in ein paar Zeilen JSL.Das meiste kann ich nachvollziehen, aber Ich habe nicht viel Erfahrung mit der Definition und Verwendung von Namespaces, daher habe ich eine Frage:
In der zweiten Zeile des Skripts ns Ist definiert als :
ns = new namespace( "queries" );
Dann scheint es ns wird in den Run Background()-Anweisungen neu definiert:
sql_query2 << Run Background( OnRunComplete(
ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
Ist der Namespace innerhalb von sql_query1 & 2 derselbe Namespace wie der, der am Anfang des Skripts definiert wurde, scheint es, als müsste er einer sein, oder es handelt sich um einen Namespace, der aufgrund der lokal für die Abfrageanweisung ist Namen standardmäßig hier(1) Aussage am Anfang? Warum tut ns Muss in der Run Background()-Anweisung definiert werden?
Nochmals vielen Dank für den einfachen, klaren und schönen Code.
Betreff: Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufTrotzdem ein nettes Stück Code, auf das man in einer schwierigen Situation verweisen kann. : )
Betreff: Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufHallo @Byron_JMP ,
Ich stimme zu, wenn das Ziel darin besteht, den Status interaktiv ausgeführter Abfragen zu überprüfen, sollte ein Benutzer nicht weiter als bis zum Abfrage-Generator suchen.Dieses Statusfenster sollte die Teile der Arbeit mit Abfragen veranschaulichen, die Benutzer bei einfachen Websuchen nur schwer finden konnten, z. B. das Referenzieren von Ergebnissen in einem Skript nach dessen Abschluss. Ehrlich gesagt erinnere ich mich, dass es mir schwer fiel, ein Minimalbeispiel zu finden.Ich bin mir sicher, dass es da draußen einen besseren Anwendungsfall gibt ...
Betreff: Führen Sie Abfragen im Hintergrund aus, warten Sie, bis sie abgeschlossen sind, und verweisen Sie im verbleibenden JSL-Skript daraufDas klingt nach einer wirklich faszinierenden Projektidee.
Ich wollte nur darauf hinweisen, dass es im Query Builder eine Registerkarte „Fortschritt“ gibt, auf der ich sehen kann, wie viele Abfragen ausgeführt werden und welchen Fortschritt sie haben. Vielleicht wäre dies eine Möglichkeit, die Query Builder-Plattform so zu skripten, dass sie diese Informationen anzeigt, anstatt zu versuchen, sie von Grund auf neu zu beschaffen?