Выполнение запроса с несколькими переменными в SQL Server с помощью курсора Python

#python #sql-server #pymssql

Вопрос:

Я пытаюсь выполнить несколько запросов в SQL Server, используя библиотеку pymssql.

Это мой код:

 cur = conn.cursor()
cur.execute("DECLARE @begin_time datetime, @end_time datetime, @from_lsn binary(10), @to_lsn binary(10);  
             SET @begin_time = DATEADD(day, -1, GETDATE()) ;  
             SET @end_time = GETDATE(); 
             SET @from_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', @begin_time);  
             SET @to_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', @end_time);
             SELECT * FROM cdc.fn_cdc_get_net_changes_dbo_users(@from_lsn, @to_lsn, 'all');")
output = cur.fetchall()
print(output)
conn.close()
 

Код работает нормально и выдает результат, однако, когда я вычисляю дату с помощью библиотеки Python и передаю ее в код, я получаю сообщение об ошибке.

Пример кода

 from datetime import datetime, timedelta
end_date = datetime.now()
start_date = datetime.now()   timedelta(hours=-1)

cur = conn.cursor()
query =  f"""DECLARE @begin_time datetime, @end_time datetime, @from_lsn binary(10), @to_lsn binary(10);  
                SET @begin_time = {start_date};  
                SET @end_time = {end_date}; 
                SET @from_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', @begin_time);  
                SET @to_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', @end_time); 
                SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_users (@from_lsn, @to_lsn, 'all');"""
print(query)
cur.execute(query)
output = cur.fetchall()
print(output)
conn.close()
 

Ошибка:

Ошибка программирования: (102, Неправильный синтаксис около «11».

Сообщение об ошибке DB-Lib 20018, степень серьезности 15:
Общая ошибка SQL Server: Проверка сообщений с сервера SQL

Я не уверен, что я здесь делаю не так. Был бы очень признателен, если бы кто-нибудь мог мне помочь и объяснить проблему.

Комментарии:

1. сообщение об ошибке показывает, что его синтаксис неверен

2. вот что я не могу понять, где я получаю неправильный синтаксис, так как тот же запрос отлично работает, когда я вычисляю время с помощью sql-запроса.

3. Возможно, это связано с тем, как формат данных передается в блок sql server. можете ли вы передать время начала в формате ГГГГ-ММ-ДД hh24:mi:ss

4. я пробовал это, но это не сработало 🙁

5. Когда вы печатаете запрос, ваши значения даты заключены в ' символы? Вы можете попробовать использовать параметры привязки , чтобы убедиться, что они обрабатываются правильно.

Ответ №1:

Рассмотрите фактическую параметризацию SQL переменных времени, а не интерполяцию строк или объединение с F-строками, что, как правило, небезопасно или неэффективно для передачи значений с уровня приложения в серверную базу данных. Библиотека, pymssql , поддерживает параметры. Python datetime.datetime должен быть переведен на MSSQL DATETIME .

 # PREPARED STATEMENTS WITH %s PLACEHOLDERS
query = """DECLARE @begin_time datetime, @end_time datetime, @from_lsn binary(10), @to_lsn binary(10);  
           SET @begin_time = %s;  
           SET @end_time = %s; 
           SET @from_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', @begin_time);  
           SET @to_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', @end_time); 
           SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_users (@from_lsn, @to_lsn, 'all');
        """
print(query)

# EXECUTE QUERY WITH BINDED PARAMS
cur.execute(query, [start_date, end_date])
 

На самом деле, вы можете сократить запрос, так как параметры не нуждаются в объявлении:

 # PREPARED STATEMENTS WITH %s PLACEHOLDERS
query = """DECLARE @from_lsn binary(10), @to_lsn binary(10);
           SET @from_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', %s);  
           SET @to_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', %s); 
           SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_users (@from_lsn, @to_lsn, 'all');
        """
 

Кстати, обратите внимание pymmsql , что библиотека больше не обслуживается. Рассмотрите pyodbc возможность наиболее безопасного, обновленного DB-API для подключений Python-SQL Server. Но обратите внимание, что заполнителем параметров для pyodbc является qmarks ? , а не %s (в отличие от большинства API-интерфейсов Python DB).

Комментарии:

1. Рад помочь! Счастливого кодирования!