Platzhalter in MySQLdb

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Caldar
User
Beiträge: 46
Registriert: Sonntag 17. Mai 2009, 18:20

Gibt es eine Möglichkeit, bei CREATE TABLE-Befehlen Platzhalter zu verwenden. Ich will eine Tabelle abhängig von der Anzahl und den Namen einer Liste erstellen lassen.
Die Liste sehe z.B. so aus

Code: Alles auswählen

liste = [("abc"),("def)"]
Nun will ich folglich eine Tabelle erstellen, die aus 2 Spalten besteht, in MySQL-Syntax also:
CREATE TABLE (`abc` VARCHAR(20), `def` VARCHAR(20))

Wenn ich nun aber folgendes versuche:

Code: Alles auswählen

curs.executemany("""CREATE TABLE temp(
    %s VARCHAR(30),
    %s VARCHAR(30)
    )""", x)
schlägt dies fehl. Kann es sein, dass der executemany-Befehl nur bei SELECT-Queries funktioniert und ich gar keine Möglichkeit habe, dies zu realisieren?
Caldar
User
Beiträge: 46
Registriert: Sonntag 17. Mai 2009, 18:20

Ich habs jetzt so gelöst, indem ich mir aus der Liste eine SQL-Query als String zusammengebaut habe, also:

Code: Alles auswählen

sql = "CREATE TABLE temp (%s VARCHAR(30), %s VARCHAR(30))" % ("abc","def")
und diese dann per

Code: Alles auswählen

curs.execute(sql)
ausführe

Edit:
Das Problem ist aber immer noch, dass ja meine Liste eine unterschiedliche Anzahl von Einträgen enthalten kann und ich ja so viele Spalten erstellen will, wie ich EIntrage in der Liste habe.
BlackJack

@Caldar: Die Platzhalter sind nur für Werte, weil die entsprechend der Regeln für Werte "ecape"t werden.

Ich denke Du hast `executemany()` missverstanden. Es gibt keine Beschränkung auf bestimmte SQL-Konstrukte, ausser das Platzhalter für Werte darin vorkommen sollten. Die ganze Anweisung wird mit jedem Satz von Werten ausgeführt, der in dem "iterable" steht, welches übergeben wird. Der Gedanke dabei ist, das halbwegs intelligente DBMS die SQL-Anweisung nur einmal Parsen,in internen "Code" übersetzen, und dann auf die Werte-"Sätze" anwenden, statt für jeden Satz von Werten die SQL-Anfrage erneut zu verarbeiten.
Caldar
User
Beiträge: 46
Registriert: Sonntag 17. Mai 2009, 18:20

Okay, es müsste also auch für CREATE TABLE-Befehle funktionieren mit den executemany-Befehl. Der Platzhalter-Gedanke war mir schon klar, nur dass es mit meinem Bsp. nicht funktionirt, irritiert mich.
Ich kann auch mal den kompletten Code posten, vielleicht erkennst Du da einen Fehler, den ich mache:

Code: Alles auswählen

fobj = open("D:\\file.csv", "r")
cols = fobj.readline()
cols = cols.strip()
col_list =  cols.rsplit(";")
fobj.close()
conn = MySQLdb.connect("localhost", "root", db="xyz")
curs = conn.cursor()
curs.executemany("""CREATE TABLE temp (%s VARCHAR(30), %s VARCHAR(30))""",col_list)
Die Fehlermeldung, die ich bekomme, ist:
TypeError: not enough arguments for format string

col_list sieht in der Konsole so aus, wenn ich ihn über eine for Schleife ausgebe:

Code: Alles auswählen

for item in col_list:
    print item
"abc"
"def"
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich glaube du hast es immernoch nicht verstanden.
`executemany` führt das Statement mehrmals aus, das Iterable muss aber ein komplettes Statement bereitstellen, dh in deinem Fall pro Iteration 2 Werte liefern.
Für deinen Zweck brauchst du nur ein einfaches `execute`. Oder, wenn du wirklich mehrere Tabellen erzeugen willst ein Iterable mit Paaren wie zb ("abc", "def").
Antworten