Python 百分比计算的查询参数出现语法错误

Python 百分比计算的查询参数出现语法错误,python,sql-server,python-3.x,sql-server-2014,pyodbc,Python,Sql Server,Python 3.x,Sql Server 2014,Pyodbc,我有一个pyodbc查询,它工作得很好,但我正在尝试应用更新来向结果中添加一个新的计算字段。工作查询是: cursor = cnxn.cursor() cursor.execute("SELECT RestaurantLocation.ID, Restaurant.DisplayName FROM Restaurant INNER JOIN RestaurantLocation ON Restaurant.ID = RestaurantLocation.Restaurant_

我有一个pyodbc查询,它工作得很好,但我正在尝试应用更新来向结果中添加一个新的计算字段。工作查询是:

cursor = cnxn.cursor()
cursor.execute("SELECT RestaurantLocation.ID, Restaurant.DisplayName FROM 
    Restaurant INNER JOIN RestaurantLocation ON Restaurant.ID = 
    RestaurantLocation.Restaurant_ID WHERE (RestaurantLocation.Active = 1)")
row = cursor.fetchall()

columns = [column[0] for column in cursor.description]
for ID,DisplayName in row:
    DisplayName = DisplayName.replace(" ","")
    cursor = cnxn.cursor()
    cursor.execute("SET NOCOUNT ON; SELECT ScheduledService.ServiceDate, 
    Restaurant.DisplayName AS RestaurantName, InvoiceLineItem.Invoice_ID, 
    ScheduledRestaurantService.Location_ID, ScheduledService.Service_ID, 
    Service.DisplayName AS ServiceName, InvoiceLineItem.Description, 
    InvoiceLineItem.Amount AS 'Subtotal' INTO #Subtotal FROM 
    ScheduledService INNER JOIN Invoice ON ScheduledService.Invoice_ID = 
    Invoice.ID INNER JOIN InvoiceLineItem ON Invoice.ID = 
    InvoiceLineItem.Invoice_ID INNER JOIN Payment ON Invoice.ID = 
    Payment.RelatedInvoice_ID INNER JOIN ScheduledRestaurantService ON 
    ScheduledService.ID = ScheduledRestaurantService.ID INNER JOIN 
    RMenuAllocatedScheduleSlot ON ScheduledRestaurantService.TimeSlot_ID = 
    RMenuAllocatedScheduleSlot.ID INNER JOIN [User] ON 
    ScheduledService.RelatedUser_ID = [User].ID INNER JOIN 
    RestaurantLocation ON ScheduledRestaurantService.Location_ID = 
    RestaurantLocation.ID INNER JOIN Restaurant ON 
    RestaurantLocation.Restaurant_ID = Restaurant.ID INNER JOIN Service ON 
    ScheduledService.Service_ID = Service.ID WHERE 
    (ScheduledService.ServiceDate BETWEEN ? AND ?) AND (NOT 
    (ScheduledService.Status_ID = 6)) AND (ScheduledService.Service_ID IN 
    (17, 18, 23, 24, 25)) AND (InvoiceLineItem.Description IN ('Subtotal')) 
    AND (ScheduledRestaurantService.Location_ID = ?) SELECT 
    #Subtotal.Invoice_ID, InvoiceLineItem.Amount AS 'SalesTax' INTO 
    #SalesTax FROM #Subtotal LEFT OUTER JOIN InvoiceLineItem ON 
    #Subtotal.Invoice_ID = InvoiceLineItem.Invoice_ID WHERE 
    (InvoiceLineItem.Description IN ('Sales Tax')) SELECT 
    #Subtotal.Invoice_ID, CASE WHEN #Subtotal.Service_ID IN (17,23,25,26) 
    THEN 0.00 ELSE InvoiceLineItem.Amount END AS 'Tip' INTO #Tip FROM 
    #Subtotal LEFT OUTER JOIN InvoiceLineItem ON #Subtotal.Invoice_ID = 
    InvoiceLineItem.Invoice_ID WHERE (InvoiceLineItem.Description IN 
    ('Tip')) Select #Subtotal.ServiceDate, #Subtotal.RestaurantName, 
    #Subtotal.Invoice_ID, #Subtotal.Location_ID, #Subtotal.Service_ID, 
    #Subtotal.Subtotal, #SalesTax.SalesTax, #Tip.Tip Into #Final From 
    #Subtotal LEFT OUTER JOIN #SalesTax ON #Subtotal.Invoice_ID = 
    #SalesTax.Invoice_ID LEFT OUTER JOIN #Tip ON #Subtotal.Invoice_ID = 
    #Tip.Invoice_ID SET NOCOUNT OFF; Select * From #Final Order By 
    #Final.Service_ID, #Final.ServiceDate Drop Table #Subtotal Drop Table 
    #SalesTax Drop Table #Tip Drop Table #Final", (firstDay,lastDay,ID))
    rows = cursor.fetchall()
那里的一切都很好。第二个查询的结果基于第一个查询中创建的唯一ID

但是,当我尝试向第二个查询添加新的计算字段时,我从SQL数据库中得到了一个不正确的语法错误。以下是更新后的查询:

cursor = cnxn.cursor()
cursor.execute("SELECT RestaurantLocation.ID, Restaurant.DisplayName FROM 
    Restaurant INNER JOIN RestaurantLocation ON Restaurant.ID = 
    RestaurantLocation.Restaurant_ID WHERE (RestaurantLocation.Active = 1)")
row = cursor.fetchall()

columns = [column[0] for column in cursor.description]
for ID,DisplayName in row:
    DisplayName = DisplayName.replace(" ","")
    cursor = cnxn.cursor()
    print(firstDay,lastDay,ID)
    if ID == 13:
        percentage = 0.18
    else:
        if ID == 25:
            percentage = 0.18
        else:
            percentage = 0.20
    cursor.execute("SET NOCOUNT ON; SELECT ScheduledService.ServiceDate, 
        Restaurant.DisplayName AS RestaurantName, 
        InvoiceLineItem.Invoice_ID, ScheduledRestaurantService.Location_ID, 
        ScheduledService.Service_ID, Service.DisplayName AS ServiceName, 
        InvoiceLineItem.Description, InvoiceLineItem.Amount AS 'Subtotal' 
        INTO #Subtotal FROM ScheduledService INNER JOIN Invoice ON 
        ScheduledService.Invoice_ID = Invoice.ID INNER JOIN InvoiceLineItem 
        ON Invoice.ID = InvoiceLineItem.Invoice_ID INNER JOIN Payment ON 
        Invoice.ID = Payment.RelatedInvoice_ID INNER JOIN 
        ScheduledRestaurantService ON ScheduledService.ID =                                                 
        ScheduledRestaurantService.ID INNER JOIN RMenuAllocatedScheduleSlot 
        ON ScheduledRestaurantService.TimeSlot_ID = 
        RMenuAllocatedScheduleSlot.ID INNER JOIN [User] ON 
        ScheduledService.RelatedUser_ID = [User].ID INNER JOIN 
        RestaurantLocation ON ScheduledRestaurantService.Location_ID = 
        RestaurantLocation.ID INNER JOIN Restaurant ON 
        RestaurantLocation.Restaurant_ID = Restaurant.ID INNER JOIN Service 
        ON ScheduledService.Service_ID = Service.ID WHERE 
        (ScheduledService.ServiceDate BETWEEN ? AND ?) AND (NOT 
        (ScheduledService.Status_ID = 6)) AND (ScheduledService.Service_ID 
        IN (17, 18, 23, 24, 25)) AND (InvoiceLineItem.Description IN 
        ('Subtotal')) AND (ScheduledRestaurantService.Location_ID = ?) 
        SELECT #Subtotal.Invoice_ID, InvoiceLineItem.Amount AS 'SalesTax' 
        INTO #SalesTax FROM #Subtotal LEFT OUTER JOIN InvoiceLineItem ON 
        #Subtotal.Invoice_ID = InvoiceLineItem.Invoice_ID WHERE 
        (InvoiceLineItem.Description IN ('Sales Tax')) SELECT 
        #Subtotal.Invoice_ID, CASE WHEN #Subtotal.Service_ID IN 
        (17,23,25,26) THEN 0.00 ELSE InvoiceLineItem.Amount END AS 'Tip' 
        INTO #Tip FROM #Subtotal LEFT OUTER JOIN InvoiceLineItem ON 
        #Subtotal.Invoice_ID = InvoiceLineItem.Invoice_ID WHERE 
        (InvoiceLineItem.Description IN ('Tip')) Select 
        #Subtotal.ServiceDate, #Subtotal.RestaurantName, 
        #Subtotal.Invoice_ID, #Subtotal.Location_ID, #Subtotal.Service_ID, 
        #Subtotal.Subtotal, #SalesTax.SalesTax, #Subtotal.Subtotal * .? AS 
        Discount, #Tip.Tip Into #Final From #Subtotal LEFT OUTER JOIN 
        #SalesTax ON #Subtotal.Invoice_ID = #SalesTax.Invoice_ID LEFT OUTER 
        JOIN #Tip ON #Subtotal.Invoice_ID = #Tip.Invoice_ID SET NOCOUNT OFF; 
        Select * From #Final Order By #Final.Service_ID, #Final.ServiceDate 
        Drop Table #Subtotal Drop Table #SalesTax Drop Table #Tip Drop Table 
        #Final", (firstDay,lastDay,ID,percentage))
    rows = cursor.fetchall()
错误是由我分配给percentage的值引发的。我首先尝试使用int来解决这个问题,因此我的IF语句变成:

if ID == 13:
    percentage = int(0.18)
else:
    if ID == 25:
        percentage = int(0.18)
    else:
        percentage = int(0.20)
我的错误是无法识别整数是使用无小数位数转换的。因此,我更新了IF语句以使用float:

if ID == 13:
        percentage = float(0.18)
    else:
        if ID == 25:
            percentage = float(0.18)
        else:
            percentage = float(0.20)
在使用float设置百分比后,我从SQL中得到了完全相同的错误。我尝试了上面IF语句的多种变体,但它们都会导致完全相同的错误


我做错了什么?

错误是由第四个参数占位符前面的小数点引起的:

... 小计,小计*。?作为折扣 这导致pyodbc使用如下查询调用sp_prepexec

选择小计。小计*@P1作为小计的折扣 这是无效的语法

参数占位符应始终单独显示,并且永远不要依赖分隔符或命令文本的其他元素来修改其行为。在这种情况下,

sql=选择id、小计、小计。小计*?作为小计的折扣 参数=十进制'0.05', crsr.executesql,参数 哪个发送

执行sp_prepexec@p1输出,N'@p1 numeric3,3',N'选择id,小计,小计。小计*@p1作为小计的折扣,50
并且执行时不会出错。

以下是pyodbc如何将Python转换为ODBC数据类型的列表:能否尝试在if语句中使用Decimal而不是float?您需要使用“从十进制导入十进制”导入is。此外,您可以在cursor.execute代码中使用三重引号,这将允许您更好地为SQL分配空间。这有助于保持我的理智!我将研究使用三重引号。使用PYODBC让我发疯的原因之一是,我的所有查询都在一个长串接字符串中。这几乎不可能解决问题。下面是一个示例:如果您不关心空格,我不关心,您可以直接在cursor.execute.no中使用相同的示例。空格一点也不困扰我,事实上它使查询更易于阅读。谢谢你的参考,这肯定会对我正在进行的大量项目有所帮助。好吧,我完全忽略了这个问题。我将我的基本SQL查询转换为在Python中使用,插入了参数,并保留了多余的字符。感谢您的帮助和发现错误。现在我已经消除了杂散周期,它工作得非常完美。