PyQt5 QSQLQuery: Данные столбца адреса из SQL базы данных, где заголовок содержит косую черту

Вопросы и ответы

Я извлекаю данные из таблицы SQL, в которой один из заголовков столбца содержит斜线 – он называется “Massflow_g/h”. К сожалению, я не владелец таблицы, и по некоторым причинам заголовки таблицы больше не могут быть изменены. С помощью QSqlQuery я получаю данные, а с помощью QSqlQueryModel отображаю данные в QTableView. Мне нужно отобразить только определенные столбцы таблицы – поэтому мне нужно выбрать и указать этот конкретный столбец в моем SQL-запросе. Но с斜线 в сочетании с PyQt5 это, похоже, невозможно… Этот вопрос задавался в похожем виде несколько раз в прошлом, но я все еще не могу найти работающее решение. Пожалуйста, кто-нибудь может помочь?

Мой код (без части для доступа к базе данных) представлен ниже. Я получаю первую таблицу из базы данных. Из нее я выбираю одну строку. Нажав кнопку “Подтвердить”, я получаю подробные данные для этой конкретной строки (подробные данные хранятся во второй таблице – ID является связующим звеном между первой и второй таблицей).

import sys

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, pyqtSlot, QRect

from PyQt5.QtCore import QSize, Qt
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery, QSqlQueryModel

from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QPushButton

#####
# отсутствующая часть - здесь база данных открывается через db = QSqlDatabase.addDatabase(...) & db.open
#####

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.UpperTable = QTableView()
        self.LowerTable = QTableView()

        self.ConfirmButton = QPushButton("Подтвердить выбор")
        self.ConfirmButton.clicked.connect(self.ReadChosenLine)

        layout = QVBoxLayout()
        layout.addWidget(self.UpperTable)
        layout.addWidget(self.ConfirmButton)
        layout.addWidget(self.LowerTable)

        self.model1 = QSqlQueryModel()
        self.UpperTable.setModel(self.model1)

        self.model2 = QSqlQueryModel()
        self.LowerTable.setModel(self.model2)  

        query1 = QSqlQuery("SELECT "
                           "Compressor_ID, Model, Generation "
                           "FROM dbo.BasicDataTable", db=db)     
        self.model1.setQuery(query1)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

    def ReadChosenLine (self, ConfirmButton):
        Zeilennummern = self.UpperTable.selectionModel().selectedRows() 
        for Zähler in Zeilennummern:
            PrimaryKey = self.UpperTable.model().data(self.UpperTable.model().index(Zähler.row(), 0))
            self.TestDetails(PrimaryKey)

    def TestDetails(self, PrimaryKey):
        query2 = QSqlQuery("SELECT *"
                           ##  "Tevap_super_C "# , Massflow_g/h " 
                           "FROM dbo.MeasurementData "
                           "WHERE Parts_ID = '{PrimaryKey}'""".format(PrimaryKey=PrimaryKey), db=db)
        self.model2.setQuery(query2)

        TableHeader = []
        for i in range(self.model2.columnCount()):
            TableHeaderSingleColumn = self.model2.headerData(i, QtCore.Qt.Horizontal)
            TableHeader.append(TableHeaderSingleColumn)
        print(TableHeader)
        # здесь мы получаем все заголовки - проблемный заголовок показан на скриншоте

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Скриншот проблемного заголовка:
введите описание изображения здесь

Изменив SQL-запрос на:

        query2 = QSqlQuery("SELECT "
                           "Tevap_super_C "# , Massflow_g/h " 
                           "FROM dbo.MeasurementData 

мой запрос все равно работает, отображается только этот столбец “Tevap_super_C”:

введите описание изображения здесь

Не работающие версии (попытки отобразить столбец “Massflow_g/h”:

        query2 = QSqlQuery("SELECT "
                           "Tevap_super_C , Massflow_g/h " 
        query2 = QSqlQuery("SELECT "
                           "Tevap_super_C , Massflow_g\/h " 

также это не работает с двумя обратными слэшами….

Тогда это не работает:

        massflow = r'Massflow_g/h'
        query2 = QSqlQuery("SELECT "
                           "Tevap_super_C , massflow "# Massflow_g\\/h " 

Следующий интересный момент – это записывается “massflow” в каждую строку:

        massflow = r'Massflow_g/h'
        query2 = QSqlQuery("SELECT "
                           "Tevap_super_C , 'massflow' " # Massflow_g\\/h " 
                           "FROM dbo.PD_Measured "

введите описание изображения здесь
и так далее…

Я уже использовал “select *”, а затем “self.table.setColumnHidden” – чтобы отобразить только интересующие столбцы – но тогда моя дальнейшая программа не работает (мне нужно дать каждой заголовке таблицы кнопку фильтра). Поэтому это временное решение тоже не подходит…

Ответ

Чтобы обратиться к столбцу в SQL-запросе, в имени которого есть знак "/", необходимо заключить имя столбца в двойные кавычки (или одинарные, в зависимости от используемой базы данных). Проблема, с которой вы столкнулись, связана именно с тем, как SQL обрабатывает имена столбцов с особыми символами.

Вам потребуется изменить запрос, добавив кавычки вокруг имени столбца «Massflow_g/h» для правильного обращения к этому столбцу. Вот как это можно сделать:

Изменение SQL-запроса

Замените свой код в функции TestDetails следующим образом:

def TestDetails(self, PrimaryKey):
    query2 = QSqlQuery("SELECT "
                       "Tevap_super_C, \"Massflow_g/h\" "  # Используйте кавычки для имен столбцов с символами
                       "FROM dbo.MeasurementData "
                       "WHERE Parts_ID = '{PrimaryKey}'".format(PrimaryKey=PrimaryKey), db=db)
    self.model2.setQuery(query2)

Полный код

Вот полный фрагмент кода функции TestDetails с учетом изменений:

def TestDetails(self, PrimaryKey):
    query2 = QSqlQuery("SELECT "
                       "Tevap_super_C, \"Massflow_g/h\" "  
                       "FROM dbo.MeasurementData "
                       "WHERE Parts_ID = '{PrimaryKey}'".format(PrimaryKey=PrimaryKey), db=db)
    self.model2.setQuery(query2)

    TableHeader = []
    for i in range(self.model2.columnCount()):
        TableHeaderSingleColumn = self.model2.headerData(i, QtCore.Qt.Horizontal)
        TableHeader.append(TableHeaderSingleColumn)
    print(TableHeader)

Дополнительные замечания

  1. Проверьте базу данных: Убедитесь, что база данных, с которой вы работаете, поддерживает использование двойных кавычек для имен столбцов. В большинстве SQL диалектов (например, PostgreSQL, Oracle) это допустимо.

  2. Обработка ошибок: Рекомендуется добавить обработку ошибок при выполнении SQL-запроса, чтобы убедиться, что запрос выполняется успешно и данные возвращаются без ошибок.

  3. Фильтры: Поскольку вы хотите использовать заголовки таблицы для фильтров, вы можете использовать метод setColumnHidden, как вы планировали, после установки модели, чтобы скрыть ненужные столбцы.

Заключение

Использование двойных кавычек вокруг имени столбца позволит вам корректно обращаться к столбцу с символом “/”. После этого ваш код должен работать без ошибок, и вы сможете отображать нужные данные в таблице. Если возникнут дополнительные вопросы, не стесняйтесь обращаться.

Оцените материал
Добавить комментарий

Капча загружается...