Не удается запустить запрос выбора mssql с предложением where в python с использованием pypyodbc

Я использую библиотеку pypyodbc и пытаюсь выполнить запрос select в mssql, используя предложение where.

Однако ошибка, которую я получаю, указывает на то, что синтаксис неверен.

Error here ('42000', "[42000] [FreeTDS][SQL Server]Incorrect syntax near the keyword 'User'.")

мой запрос в моей функции выглядит следующим образом:

try:

    selectUserDetails = "SELECT Username,Password FROM User WHERE Username = ?"
   cursor.execute(selectUserDetails,(username,))

    for row in cursor:
        print(row);

except Exception as e:

    print('Error here ' + str(e))

Моя функция для получения курсора выглядит следующим образом:

def msDbCred():


try:
    from msDb import connection_string

    conn = pypyodbc.connect(connection_string)
    cursor = conn.cursor();
    return cursor;

except pymysql.err.OperationalError:
    sys.exit("Invalid Input: Wrong username/db or password found, please try again")

cursor = msDbCred()

и мои учетные данные базы данных хранятся в другом файле с именем msDb.py

db_host = '127.0.0.1'
db_name = 'TD_1.0'
db_user = 'ReadOnly'
db_password = 'mypaswword'

connection_string = 'Driver=SQL Server;Server=' + db_host + ';Database=' + db_name + ';uid=' + db_user + ';PWD=' + db_password + ';'

Мой вопрос здесь в том, что-то не так с самим запросом. Поскольку я использую этот же формат в другом запросе в другом месте моего кода, и он работает. Или что-то еще не так с моими функциями?

ОБНОВИТЬ:

@Горд Томпсон сказал, что я должен изменить свой запрос.

я изменился, мой запрос;

selectUserDetails = "SELECT Username FROM [TD_1.0].[dbo].[User] WHERE Username = ?"
cursor.execute(selectUserDetails,(username,))

Однако теперь я получаю сообщение об ошибке;

('HY010', '[HY010] [unixODBC][Driver Manager]Function sequence error')

person mp252    schedule 30.03.2017    source источник
comment
Попробуйте заключить имя таблицы в квадратные скобки: [User]   -  person Gord Thompson    schedule 30.03.2017
comment
@GordThompson Я изменил свой запрос в соответствии с вашим комментарием, но теперь получаю другую ошибку. Как показано выше в обновлении   -  person mp252    schedule 31.03.2017
comment
USER — это ключевое слово. Вы должны обернуть его, например, [User]. Вам необязательно использовать имя, состоящее из трех частей. Кроме того, в вашем запросе используется ? , что не соответствует тому, как параметры используются в SQL Server. FreeTDS все равно не поддерживает параметры, в лучшем случае выполняет подстановку. Дальнейшие проблемы - вместо хранения и сравнения хэшей вы загружаете пароль пользователя? Это почти напрашивается на взлом, как в новостях.   -  person Panagiotis Kanavos    schedule 31.03.2017
comment
Почему вы используете FreeTDS? Почему бы вам не использовать ODBC напрямую? Что касается проверки паролей, правильный способ сделать это — использовать надежный криптографический алгоритм хеширования с как минимум 1000 итерациями для генерации и хранения хэша из пароля и солт-значения. Всякий раз, когда пользователь пытается войти в систему, снова сгенерируйте хэш и сравните его с сохраненным хэшем.   -  person Panagiotis Kanavos    schedule 31.03.2017
comment
Ознакомьтесь с документацией Microsoft по подключению к SQL Server. из Python с помощью pymssql или pyodbc. Проверьте Как использовать параметры SQL с python? о том, как использовать настоящие параметризованные запросы с pymssql   -  person Panagiotis Kanavos    schedule 31.03.2017
comment
@PanagiotisKanavos re: ваш запрос использует ? , но это не то, как параметры используются в SQL Server. Это это то, как параметры используются в pypyodbc, pyodbc и многих (если не в большинстве) других широко используемых уровнях доступа ODBC. ; re: FreeTDS в любом случае не поддерживает параметры, в лучшем случае она выполняет подстановку. — Это может быть правдой, когда FreeTDS_ODBC действительно общается с SQL Server, но по-прежнему рекомендуется использовать параметры на уровне Python. . ; re: Почему вы используете FreeTDS? Почему вы не используете ODBC напрямую? - Пожалуйста, объясните, что вы подразумеваете под прямым использованием ODBC.   -  person Gord Thompson    schedule 31.03.2017
comment
Я не могу воспроизвести вашу ошибку. Вы можете выполнить простой запрос, например SELECT COUNT(*) AS n FROM sys.objects?   -  person Gord Thompson    schedule 31.03.2017
comment
Параметры @GordThompson в SQL Server имеют имена. Они передаются по имени, например @name. Однако некоторые драйверы не поддерживают параметры. Вот когда используется ?. В остальном я уже предоставил ссылки на руководства и вопросы, связанные с передачей параметров в фактические параметризованные запросы. Наконец, использование поддельных параметров — это ответственность, а не преимущество. Вы не можете избежать SQL-инъекции таким образом или получить какие-либо преимущества параметризации, но код делает вид, что это не так.   -  person Panagiotis Kanavos    schedule 03.04.2017
comment
@GordThompson Мне удалось решить эту проблему, ответ ниже   -  person mp252    schedule 03.04.2017


Ответы (1)


Мне удалось выяснить, где была ошибка и как ее исправить.

В моей функции msDbCred() я напрямую возвращал курсор. Я тестировал в другом файле и понял, что это проблема.

Поэтому вместо этого я создал пустой массив и добавил к нему курсор, а затем вернул массив.

Затем использовал первый индекс массива в качестве курсора в другом месте моего кода.

def msDbCred():

    cred = []
    try:
        from msDb import connection_string
        conn = pypyodbc.connect(connection_string)
        cursor = conn.cursor();
        cred.append(cursor)
        return cred
    except pymysql.err.OperationalError:
        sys.exit("Invalid Input: Wrong username/db or password found, please try again")

cursor = msDbCred()

Затем используйте первый индекс массива курсоров

try:
    selectUserDetails = "SELECT Username,Password,UserId FROM [User] WHERE Username = '"+str(username)+"' AND IsEditor = '"+str(True)+"'"
           cursor[0].execute(selectUserDetails)

    for row in cursor[0]:
        return  row[0] == username and row[1] == password
except Exception as e:
     print('Error is ' + str(e))

теперь это работает.

person mp252    schedule 03.04.2017