Ich habe eine Anwendung entwickelt, die Tabellen basierend auf externen Definitionen erstellt. Wenn sich diese Definitionen ändern, löscht die Anwendung die betroffenen Tabellen und erstellt sie neu. Dies muss geschehen, während die Verbindung geöffnet wird, da diese Aufgabe Teil einer Gruppe von Aufgaben ist. Wenn ich jedoch eine Tabelle abfrage, die sich später mit "select *" geändert hat, bekomme ich die Spalten der alten Definition. Wenn der Tabelle Spalten hinzugefügt wurden, wird "select *" nicht angezeigt. Hier ist ein Beispielcode, dies zeigt:Wie kann "select *" nach dem Ändern der Tabelle entsprechend funktionieren?
private static void OraSelectStarProblem()
{
var tabDef1 = "CREATE TABLE TEMP_PS_000 (SESSIONID RAW(16), EXECNR NUMBER, DUEDATE DATE)";
//var tabDef2 = "CREATE TABLE TEMP_PS_000 (YASESSIONID RAW(16), YAEXECNR NUMBER, YADUEDATE DATE, NEWFIELD VARCHAR2(100))";
var tabDef2 = "CREATE TABLE TEMP_PS_000 (YADUEDATE DATE, NEWFIELD VARCHAR2(100), SOMEOTHER integer)"; // causes ORA-00932 when querying
var selectCmd = "select * from TEMP_PS_000";
using (var conn = new OracleConnection(GetConnStr()))
{
conn.Open();
//PerformSelectStar(selectCmd, conn);
DropTempTable(conn);
Console.Write("Creating TEMP_PS_000 with 3 columns... ");
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = tabDef1;
cmd.ExecuteNonQuery();
}
Console.WriteLine("Done!");
PerformSelectStar(selectCmd, conn);
//conn.PurgeStatementCache(); // no effect
//conn.FlushCache(); // no effect
/*Console.WriteLine("Resetting connection");
conn.Close();
OracleConnection.ClearPool (conn);
conn.Open();*/
DropTempTable(conn);
//conn.PurgeStatementCache(); // no effect
//conn.FlushCache(); // no effect
Console.Write("Creating TEMP_PS_000 with 4 columns... ");
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = tabDef2;
cmd.ExecuteNonQuery();
}
Console.WriteLine("Done!");
PerformSelectStar(selectCmd, conn);
}
}
private static void DropTempTable(OracleConnection conn)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "begin drop_table('TEMP_PS_000'); end;";
cmd.ExecuteNonQuery();
}
}
private static void PerformSelectStar(string selectCmd, OracleConnection conn)
{
try
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = selectCmd;
var dataAdapter = new OracleDataAdapter(cmd);
var dataSet = new DataSet();
dataAdapter.Fill(dataSet);
var columns = "";
foreach (DataColumn column in dataSet.Tables[0].Columns)
{
columns += column.ColumnName + " ";
}
Console.WriteLine("Columns: " + columns);
}
}
catch (Exception ex)
{
Console.WriteLine("PerformSelectStar: " + ex.Message);
}
}
Software-Versionen verwendet: .net 4.5.1 und Oracle 12.1
Wenn der Teil, der die Verbindung zurücksetzt aktiviert, „select *“ funktioniert, aber dann Alle Daten in temporären Tabellen werden gelöscht, was nicht erwünscht ist.
Ich würde gerne wissen, ob es eine Methode gibt, ODP.net oder Oracle zu sagen - was auch immer der Grund für dieses seltsame Verhalten ist - dass die Definition einer Tabelle geändert wurde und dass sie die Tabellendefinition vor der Ausführung erneut lesen sollte "wählen *".
Warum würden Sie das tun? Scheint, als ob es den Punkt in einem relationalen Datenbanksystem trotzt und Sie sollten sich eine DocumentDB-Lösung ansehen ... Wenn Sie dies tun müssen, verwenden Sie die von der Datenbank bereitgestellten Metadatenansichten, um eine explizite Liste der Spalten zu erhalten und diese zu verwenden die Abfrage anstelle von * – Milney
@Milney Die Daten in diesen Tabellen werden in Verbindung mit SQL-Abfragen in einer normalisierten Datenbank verwendet. Während es anderswo möglich wäre, würde es auch dazu führen, dass die Abfragen komplizierter werden (d. H. Der Code wäre viel schwerer zu lesen und zu warten). –
Problem könnte gelöst werden: Der Trick besteht darin, die Anweisung in einer Weise zu ändern, die das Ergebnis nicht beeinflusst, wie hier gezeigt: http://stackoverflow.com/a/16861388/3424360 –