我有一个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 Db中得到一个“不正确的语法错误”。这是更新的查询:
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()
错误是由我分配给“百分比”的值引发的。我首先尝试使用int()来解决这个问题,所以我的IF语句变为:
if ID == 13:
percentage = int(0.18)
else:
if ID == 25:
percentage = int(0.18)
else:
percentage = int(0.20)
我的错误是没有识别int()是使用无小数位转换的。所以我更新了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语句的多种变体,但它们都会导致完全相同的错误。
我做错了什么?
答案 0 :(得分:1)
错误是由第四个参数占位符之前的句点(小数点)引起的:
... #Subtotal.Subtotal * .? AS Discount
这导致pyodbc使用类似
的查询调用sp_prepexec
SELECT ... #Subtotal.Subtotal * .@P1 AS Discount FROM #Subtotal
这是无效的语法。
参数占位符应始终独立显示,并且永远不要依赖分隔符或命令文本的其他元素来修改其行为。在这种情况下,
sql = "SELECT id, Subtotal, #Subtotal.Subtotal * ? AS Discount FROM #Subtotal"
params = (Decimal('0.05'),)
crsr.execute(sql, params)
发送
exec sp_prepexec @p1 output,N'@P1 numeric(3,3)',N'SELECT id, Subtotal, #Subtotal.Subtotal * @P1 AS Discount FROM #Subtotal',50
并执行且没有错误。