Zugriff mit pymssql auf MS-SQL Server

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Hallo,

ich versuche schon Tagelan vergeblich Daten eines SQL-Servers mir Python2.7 auszulesen.
Ich verwende einen RaspBerry.
Hier die Daten aus der OS
PRETTY_NAME="Raspbian GNU/Linux 7 (wheezy)"
NAME="Raspbian GNU/Linux"
VERSION_ID="7"
VERSION="7 (wheezy)"
ID=raspbian
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"


Der Zugriff erfolgt auf einen sich im Netz befindlichen MS-SQL Server 2019

Hier mal das Script:

Code: Alles auswählen

#!/usr/bin/env python
#coding: utf-8
# *************************

from __future__ import absolute_import, division, print_function

import pymssql


conn = pymssql.connect(host='10.63.74.5', user="sa", password="xxxxxx",database= "Secure")
cursor = conn.cursor()
print("Tabelle anlegen")

cursor.execute("""
IF OBJECT_ID('MeineTabelle', 'U') IS NOT NULL
    DROP TABLE MeineTabelle
    CREATE TABLE MeineTabelle(
    IDx INT NOT NULL,
    Name VARCHAR(50),
    Ort VARCHAR(20),
    PRIMARY KEY(IDx)
)
""")
print("Tabelle angelegt - Daten einpflegen")
cursor.executemany(
    "INSERT INTO MeineTabelle VALUES (%d, %s, %s)",
    [(1, 'Alex Muster', 'Musterstadt'),
     (2, 'Hans Tester', 'Testerstadt'),
     (3, 'Max Mayer', 'Nirgendwoooo')])

conn.commit() # Speichern der Daten

cursor.execute('SELECT * FROM MeineTabelle')
row = cursor.fetchall()

print("Die eingegenben Daten ausgeben")
while row:
    print(row[0], row[1], row[2])
    row = cursor.fetchone()
    
Columns=[i[0] for i in cursor.description]
print("Ergebnis von Columns ausgeben" + str(Columns))
cursor.execute("Drop Table MeineTabelle")
print("Tabelle wieder entfernen und Connection schließen")
conn.close()
Das Ergebnis sieht so aus:

Code: Alles auswählen

Python 2.7.3 (default, Jun 22 2016, 03:14:32) 
[GCC 4.6.3] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
Tabelle anlegen
Tabelle angelegt - Daten einpflegen
Die eingegenben Daten ausgeben
Ergebnis von Columns ausgeben['IDx', 'Name', 'Ort']
Tabelle wieder entfernen und Connection schließen
>>> 
Es erfolgt keine Ausgabe des Inhalts der Tabelle. Die Tabelle mit Inhalt kann ich im MM-Studio sehen und sind korrekt.
Das gleiche Spiel habe ich mit _mssql durchgespielt. Es geht das gleiche wie mit pymssql. Auch hier bekomme ich keine Daten angezeigt.

die neuesen Versionen habe ich so installiert:

apt-get install python-pymssql
apt-get install freetds-dev
pip install pymssql


Ich hoffe ich habe in meinem Posting nichts vergessen. Ich bin mit sicherheit kein Python-Profi und bitte deshalb um Nachsicht. Das Script habe ich extra so hintereinander geschrieben um die Sache nicht zu verkomplizieren.

Vielleicht hat ja jemand einen Tipp fur mich?
Das Betriebssystem der Raspis geht nicht einfach zu wechseln. Es handelt sich hierbei um 15 RaspBerrys, welche an den verschiedensten Standorten verbaut sind. Das Script zu ändern, wäre aber kein Problem.

Gruß S3
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Warum verwendest du Python 2.7? Das ist tot. Es gibt keinen Grund mehr darauf zu setzen. Bitte verwende eine Version, die noch unterstützt wird.

Vielleicht solltest du dir ausgeben lassen, was "row" eigentlich ist. Das sieht nämlich ein bisschen seltsam aus, was du da mit .fetchall() und .fechone() machst.
Und ich halte "row" auch für den falschen Namen für etwas, das man mit "*many" holt.
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Wenn Du den gesamten Thread gelesen hättest, würdest Du diue Frage nicht stellen. Tut mir leid, aber das nützt mir nichts.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Der Thread ist ja nicht so lang, dass man da etwas übelesen könnte ;)

Also, was ist denn row?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

sparrow hat schon recht, das was du da mit fetchall und fetchone machst, ist definitiv falsch. Und auch Tabellen anzulegen, um sie dann wieder zu löschen, ist vorsichtig ausgedrückt ein unorthodoxes Vorgehen. Das Schema einer Datenbank bleibt üblicherweise unangetastet. Und das wäre auch mein erster Kandidat für dieses Fehlverhalten. Was passiert denn, wenn du die Tabelle einmal anlegst, und einfach nur Einträge einfügst & anzeigst? Geht das?
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Row ist eine Variable, welche die Zeileninhalte beinhaltet. Es könnte auch Reihe heißen.

Ich MUSS Python 2.7 benutzen, weil das Script aller vorhandenen 15 Raspberrys eben in der Version existiert. Wenn ich Python 3 verwenden möchte, müsste ich die 15 Raspis in ein Netz mit Internet nehmen und updaten. Das ist nicht so ohne weiteres machbar. Es handelt sich um Systeme, welche an verschiedenen Standorten verbaut sind und funktionieren.

(Ich war der Annahme, meine Ausführung oben, sowie das Script wäre verständlich und vollständig )



Gruß S3
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Row ist eine Zeile. Du holst dir aber mit fetchall ALLE Zeilen. Mehrzahl. Und diese Unterscheidung ist wichtig, denn du hast dich prompt selbst verwirrt. Würde dein Code die Daten abholen, würde das print 3 ZEILEN ausgeben, statt wie du es willst die Werte der drei Spalten. Angebracht wäre also der Name rows, und der Verzicht auf fetchone(), stattdessen einfach über die Zeilen in rows iterieren.

Code: Alles auswählen

rows = cursor.fetchall()
for row in rows:
    print …
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Glaube mir, der Effekt ist der gleiche
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

@Senseo3: Du hast doch in deinem ersten Post des Threads gezeigt, dass du Pakete einfach mit apt-get installieren kannst. Da geht der geneigte Leser möglicherweise davon aus, dass du das selbstverständlich auch für Python 3 kannst. Das nachinstallieren von anderen Modulen scheint ja auch geklappt zu haben.

Ich würde, wenn __deets__' letzter Vorschlag nicht zum Erfolg führt, noch einmal dringend ans Herz legen, sich den Inhalt von "rows" einmal anzeigen zu lassen. Und sollte der leer sein, __deets__' vorherige Anmerkung ins Auge zu fassen und das Anlegen der Tabelle nicht in der selben Connection zumindest aber nicht in der selben Transaktion zu tun wie das Schreiben der Daten. Möglicherweise gibt es da Einschränkungen, die man nicht kennt.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Senseo3 hat geschrieben: Mittwoch 27. April 2022, 08:54 Glaube mir, der Effekt ist der gleiche
Glaube mir, es ist trotzdem Quatsch. Nur weil der Quatsch nicht anspringt aufgrund eines anderen Problems, ändert sich daran nix.

Und hast du meinen anderen Vorschlag ausprobiert? Weil, ohne was auszuprobieren, wird sich auch nix ändern.
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Ich habe mir mal die Mühe gemacht und das Sript angepasst.

Code: Alles auswählen

#!/usr/bin/env python
#coding: utf-8
# *************************

from __future__ import absolute_import, division, print_function

import pymssql


conn = pymssql.connect(host='10.63.74.5', user="sa", password="XXXXX",database= "Produktion")
cursor = conn.cursor()
cursor.execute('SELECT * FROM Artikel')
rows = cursor.fetchall()

for row in rows:
    print ("Ergerbnis OK") # Würde die Schleife durchlaufen, wäre dieser Eintrag sichtbar!
    
Columns=[i[0] for i in cursor.description]

# Diese Ausgabe zeigt mir, dass die Daten vorhanden sind und somit die Abfrage funktioniert
print("Ergebnis von Columns ausgeben" + str(Columns))
# Mehr ist hier nicht reinzuinterpretieren und könnte weggelassen werden

conn.close()
Im Ergebnis sehe ich die Ausgabe der Spalten - mehr nicht.
Ich habe un alle Zeilen, welche Euch - warum auch immer - verwirrt haben, gestrichen und mich auf das Grundlegende beschränkt.
Das Script sollte verdeutlichen, dass die Verbindung klappt, dass das Anlegen und füllen einer Tabelle funktioniert und dass Daten im Cursor stehen. Diese Feinheiten, ob das nun row oder rows heißt, ist für das Script irrelevant.

Ich bitte wirklich nur die zu posten, welche Ahnung von dieser Materie haben und die Lösung kennen. In allen Postings im Netz werden die Abfragen so gemacht und scheinen zu funktionieren. Warum das aber bei uns nicht funktioniert - keine Ahnung,
Hier knobeln schon einige Python-Profis an dem Fall.

Vielleicht hat ja jemand ein funktionierendes Peispiel?

Gruß S3
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Es muss wirklich schwer sein, die Vorschläge hier umzusetzen.
Aber ich interpretiere deinen Post so, dass du keine Hilfe willst. Dann knobelt mal weiter :)
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Hallo,
die Vorschläge - auch wenn sie bisher Quatsch waren, habe ich umgesetzt. Eigentlich will ich nicht knobeln. Ich dachte, ich träfe hier einen Profi, der von dieser Materie Ahnung hat und mir den entscheidenden Tipp geben kann.
Die hier gezeigten Vorschläge sind alle ungetestet - oder?

Ich habe im Netz Postings gefunden, die sich schon vor 6 Jahren mit dem Thema rumgeärgert haben. Leider waren diese ebenfalls ohne Lösung.

Mein Grundanliegen wäre, wenn ich ein Script hätte, mit dem Ich Daten aus einer Tabelle bekomme. Alles andere schaffe ich selbst. Hierfür ginge auch _mssql.

Gruß S3
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn es wirklich so wäre, dass Du mit einer frischen Connection, deine Tabelle `Artikel` abfragst und darin keine Einträge sind, aber Du die korrekten Feldnamen bekommst, dann würde ich sagen, dass in der Tabelle keine Einträge sind.

Öffnest Du in Deinem MM-Studio wirklich die selbe Datenbank? Läuft das auf dem selben Raspberry und hat die selbe Netzwerkverbindung?


PS: sinnvolle Vorschläge als Quatsch zu bezeichnen (und die Helfenden hier damit indirekt als Idioten) ist bestimmt ein gutes Vorgehen, um noch mehr Hilfe zu bekommen. Ich kann verstehen, dass Du im Moment dich über Deine Netzwerkkonfiguration ärgerst, die Schuld daran gerne jemand anderem als Dir selbst geben möchtest, aber bevor Du in diesem Zustand Posts absetzt, lass sie nochmal von jemand unabhängigen gegenlesen.
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Die Artikeltabelle ist eine unserer Programm-Tabellen mit meheren 1000 Artikeln.
Glaubst Du wirklich , ich mache solche Fehler?
Natürlich läuft der SQL-SERVER NICHT auf einem Pi. Auch hat es NICHT die gleiche Netzwerkverbindung. Der Server läuft in einem VLan für Server. Der
Raspi läuft in einem VLan für Computer etc. Das ist auch nicht die Frage, da ja die Connection steht. Zu erkennen, dass diese verbindet. Ich postete ja das Ergebnis.
Andernfalls - das sollte als Beweis dienen, bekomme ich Daten und wenn nur die Koppfdaten. Hier gilt es anzusetzen. Warum enthält der Cursor nur diese?

Übrigens - alles was Netz - MS-SQL Server VLan Portfreigaben etc angeht, bin ich die letzten 45 Jahre ziemlich schussfest. Dort ist der Fehler nicht zu suchen. Übrigens habe ich die Connection schon auf meherere vorhandene SQL-Seever gelegt. auf einen 2012er, 2016er und 2019er. Überlall das gleiche Resultat. Zum Test könnte ich mir einen Pi so ferigg machen, dass ich Internet-Zugang hätte um mit Pyton3 zu testen, nur um zu prüfen, ob das funktioniert. Leider habe ich keine Ahnung, wie und was ich alles unstallieren müßte, da ja PyMsSql für Python3 abweicht.

gruß S3
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Profis hier treffen auch immer wieder auf renitente Besserwisser, die zwar Probleme haben, die sie nicht geloest bekommen, aber gleich auf Attacke schalten, wenn man ihnen etwas vorschlaegt, das sie gar nicht begreifen. Denn wider deiner Erwartungshaltung loesen auch Profis Probleme nicht auf einen Schlag, sondern muessen sich dem annaehern, durch konkrete Experimente.

Mein (und sparrows) Vorschlag war kein auch Quatsch, sondern ein Fehler im Code, der offensichtliches Unverstaendnis darstellt. Und wenn deine Gurkenprogrammierung mit anlegen und abreissen einer Tabelle funktioniert haette, waere dir das auch aufgefallen, und du haettest hier wieder rumgenoelt, was denn da nicht geht. Es gibt halt Leute, die koennen beim Schach auch mal nen Zug oder zwei vorrausdenken. Und dann gibt's Leute, die scheissen auf's Brett und werfen es danach auf den Boden....

Und natuerlich hast du auch meinen Vorschlag nicht umgesetzt, vielleicht weil dir Lesekompetenz fehlt? Ich habe nicht gesagt, du sollt auf einer leeren Tabelle eine Abfrage durchfuehren, ich habe gesagt, du sollst auf einer *bestehenden* Tabelle Einfuegungen machen, und danach diese wieder auslesen. Wen das klappt, dann haben wir - siehe oben - einen Hinweis darauf, wo das eigentliche Problem liegen kann. Aber zu einer solchen konstruktiven Zusammenarbeit bist du offensichtlich nicht in der Lage. Also viel Spass beim rumstochern im Dunkeln.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hier, du Profi: https://docs.microsoft.com/en-us/previo ... dfrom=MSDN

"A table cannot be changed and then the new columns referenced in the same batch."

Das mischen von DDL und DML innerhalb einer Transaktion, so wie von dir gezeigt, funktioniert halt nicht. 45 Jahre schussfest, das ich nicht lache. 45 Jahre Kopfschuss vielleicht. Wenn das jemand, dessen letzte Beruehrung mit MSSQL in den 90ern war, innerhalb von 2 Minuten rausfinden kann, dann ist's wohl nicht so weit her mit deinem Erfahrungschatz.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

That made my day. :D
Senseo3
User
Beiträge: 24
Registriert: Donnerstag 2. April 2015, 08:37

Hello -deets - ( cooles Posting :D )

Mal ensthaft: (FRIEDEN :wink: )

Hier, du Profi: https://docs.microsoft.com/en-us/previo ... dfrom=MSDN

Die Aussage ist korrekt, aber das comm.commit() schreibt doch erst mal die Daten im 1. Script in die Tabelle.

Nur mal so am Rande. Das 1. Script stammt von der Internet-Seite Python.org und ist 1:1 so als Beispiel dort hinterlegt.Ich habe nur die Tabellennamen und die Connection geändert. So falsch kann das also nicht sein ODER?

Schau mal, ich lege die Tabelle an, update und lese die Tabelle wieder aus. Würde das in der gleichen Connection nicht funktionieren, würde ich nicht die Kopfdaten erhalten.
Korrigiere mich, wenn ich falsch liege.

Unter .NET z.B. connecte ich die Datenbank einmalig mit dem SQL-Server und öffne/schließe nur die Reader zum Lesen/schreiben der Tabellen.
Die Connection muss nur einmal stehen. Auch unter .NET muss ich die Daten zwischendurch schreiben um diese an anderer Stelle zu lesen.
Korrigiere mich, wenn ich falsch liege.

Als 2. Beispiel habe ich nur versucht, Daten aus einer bestehenden Tabelle zu lesen.

Kannst Du auf einen SQL-Server zugreifen? Wenn ja, was macht der 1. Code bei dir? Bekommst Du das gleiche Ergebnis oder siehst Du die Daten?

Hast Du vielleicht ein bissel funktionierenden Code, mit dem ich eie Tabelle auslesen könnte?

Gruß S3
LotharK
User
Beiträge: 51
Registriert: Sonntag 22. März 2015, 10:02

Hallo S3
Deine Fragen waren von Anfang an gut formuliert.
Du bist hier der Fragesteller. Das bedeutet: Dau, keine Ahnung, unerfahren. Dein Code ist schon ungelesen Schrott.

Dein Pi verwendet mit Sicherheit eine Version, welche damals einen Bug hatte. Du wirst Dich auf den Kopf stellen können, mit der Version funktioniert es nicht. Entweder neues Image oder so lassen.
Dein Programmschnipsel funktioniert einwandfrei. In der Connection musst Du noch "host" verwenden. Das ist das entscheidende Indiz. Richtig muss es nun "server" heißen, funktioniert bei Dir aber nicht.


Gruß LK
Antworten