2 Stimmen

Wie wählt man am besten einen Tabellennamen dynamisch zur Laufzeit?

Ich verwende MySQL Connector/Net und möchte eine Abfrage für eine Tabelle schreiben, deren Name zur Laufzeit angegeben wird.

Dieses Beispiel ist mir spontan eingefallen (nicht getestet):

public class DataAccess
{
    public enum LookupTable
    {
        Table1,
        Table2,
        Table3
    }

    public int GetLookupTableRowCount(LookupTable table)
    {
        string tableName = string.Empty;

        switch (table)
        {
            case LookupTable.Table1: 
                tableName = "table_1";
                break;
            case LookupTable.Table2: 
                tableName = "table_2";
                break;
            case LookupTable.Table3: 
                tableName = "table_3";
                break;
            default:
                throw new ApplicationException("Invalid lookup table specified.");
        }

        string commandText = string.Concat("SELECT COUNT(*) FROM ", tableName);

    // Query gets executed and function returns a value here...
    }
}

Da ich nicht glaube, dass man einen Tabellennamen in einer Abfrage parametrisieren kann, habe ich ein Enum statt einer Zeichenkette im Funktionsparameter verwendet, um die Möglichkeit von SQL-Einschleusung .

Hältst du das für einen guten Ansatz? Gibt es einen besseren Weg?

4voto

zombat Punkte 89911

Sie können keine Parametrisierung einer Kennung (Tabellenname oder Feldname) in MySQL können Sie sie jedoch mit Backticks ausblenden.

Die folgende Abfrage wird sicher ausgeführt, führt aber zu einem Fehler, weil die Tabelle nicht existiert (es sei denn, Sie haben zufällig eine Tabelle mit diesem Namen):

SELECT * FROM `users; DROP TABLE users;`;

Grundsätzlich können Sie dynamische Namen oder Felder verwenden, solange sie in Backticks eingeschlossen sind. Um auf diese Weise SQL-Injektionen zu verhindern, müssen Sie lediglich alle Backticks entfernen:

tableName = tableName.Replace("`", "");
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";

2voto

Quassnoi Punkte 396418

Dynamische Tabellennamen sind nie ein guter Ansatz (es sei denn, Sie entwickeln eine PHPMyAdmin oder etwas Ähnliches).

Wenn Ihre Tabellennamen begrenzt sind, warum erstellen Sie nicht einfach eine gespeicherte Prozedur und rufen sie mit einem Parameter auf?

DECLARE _which INT
BEGIN
        SELECT  COUNT(*)
        FROM    table_1
        WHERE    _which = 1
        UNION ALL
        SELECT  COUNT(*)
        FROM    table_2
        WHERE    _which = 2
        UNION ALL
        SELECT  COUNT(*)
        FROM    table_3
        WHERE   _which = 3
END

1voto

Bill Karwin Punkte 493880

Richtig, Sie können einen Abfrageparameter nicht für einen Tabellennamen, einen Spaltennamen, ein SQL-Schlüsselwort oder einen Ausdruck usw. verwenden. Sie können einen Abfrageparameter nur für einen einzelnen Wert verwenden.

Ich stimme zu, dass eine Art von Mapping von der Eingabe zum literalen Tabellennamen ein guter Weg ist, um sich gegen SQL-Injection zu schützen.

Ich programmiere nicht in .NET, sondern verwende normalerweise dynamische Sprachen wie PHP, Python oder Perl. Ich verwende also ein Hash-Array. Sie können das switch() wenn Sie Ihre Aufzählungsvariable einfach als Index für das Hash-Array verwenden können.

$tableName = $tableNameHash[ $table ];

Unterstützt .NET eine Datenstruktur vom Typ Hash-Map? Das ist es, wonach ich suchen würde.


Sieht aus, als gäbe es eine hash_map Klasse in der Standard-C++-Bibliothek.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X