【问题标题】:Slick MS SQL Server Filter BooleansSlick MS SQL Server 筛选布尔值
【发布时间】:2013-08-06 12:25:56
【问题描述】:

将我的项目从 MySQL 切换到 MS SQL Server 并且遇到了问题...

我正在使用 Slick,当我尝试执行查询时出现错误

[SQLServerException: Incorrect syntax near '='.]

这是超级描述性的,除了我没有看到 slick 试图执行什么。因此,经过一些调试后,我将其范围缩小到导致此异常的过滤器。

//my join
var q = for {
  license <- License
  category <- Category if license.category === category.id
  keyContact <- Contact if license.keyContact === keyContact.id
  supplierContact <- Contact if license.supplierContact === supplierContact.id
  pricing <- Pricing if license.pricing === pricing.id
  location <- Location if license.location === location.id
  } yield (license,category,keyContact,supplierContact,pricing,location)
}

//THESE are the lines that don't work!
if(!approved.isDefined)           q=q.filter(!_._1.approved)
if(!pendings.isDefined)           q=q.filter(_._1.approved)
if(!completes.isDefined)          q=q.filter(x => (
    x._5.price === -1        ||
    x._5.serverCost === -1   ||
    x._5.depreciation === -1 ||
    ((x._5.maintCost === -1  || x._5.maintCost.isNull) &&
     x._1.maintAgreement === true)
    ))
if(!incompletes.isDefined)  q=q.filter(x => (
    x._5.price =!= -1 &&
    x._5.serverCost =!= -1 &&
    x._5.depreciation =!= -1 &&
    (x._1.maintAgreement === false || x._5.maintCost =!= -1)
    ))
//The join works if I don't have these filters. I have other filters I left out that do work for simplicity and readability 

调用了 isDefined 的值只是我作为过滤器传递给函数的选项。上面的代码适用于 MySQL,但 MSSQL 似乎不喜欢它。有什么想法吗?

q=q.filter(!_._1.approved) 至少需要什么才能工作?我也试过_._1 === false

EDIT 查询的调试信息...

[debug] s.s.s.BaseSession - Preparing statement: select top 100 percent s25."id", s25."category", s25."tool", s25."supplier", s25."manufacturer", s25."licenseType", s25."version_edition", s25."location", s25."keyContact", s25."supplierContact", s25."supportedBy", s25."licenseEnd", s25."maintAgreement", s25."maintEnd",s25."count", s25."pricing", s25."compatibility_notes", s25."other_notes", s25."approved", s26."id", s26."name", s27."id", s27."nameFirst", s27."nameLast", s27."email", s27."phone", s28."id", s28."nameFirst", s28."nameLast", s28."email", s28."phone", s29."id", s29."price", s29."licenseOneTime", s29."depreciation", s29."maintCost", s29."serverCost", s29."purchCostSaved", s29."maintCostSaved", s30."id", s30."name", s30."city", s30."state", s30."country", s30."contact" from "licenses" s25, "categories" s26, "contacts" s27, "contacts" s28, "pricing" s29, "locations" s30 where (((((s25."category" = s26."id") and (s25."keyContact" = s27."id")) and (s25."supplierContact" = s28."id")) and (s25."pricing" = s29."id")) and (s25."location" = s30."id")) and (not s25."approved") order by s26."name", s25."tool", s25."manufacturer", s30."name", s25."supplier"

有用的部分是最后。请注意,这只是在未定义批准时进行查询。

解决方案 我所做的是在应用方法期间更改我的预测以进行类型转换。

def * = id ~ category ~ tool ~ supplier ~ manufacturer ~ licenseType ~ version_edition ~
location ~ keyContact ~ supplierContact ~ supportedBy.? ~ licenseEnd.? ~ maintAgreement ~
maintEnd.? ~ count ~ pricing ~ compatibility_notes.? ~ other_notes.? ~ approved <> (
{l => License(l._1,l._2,l._3,l._4,l._5,l._6,l._7,l._8,l._9,l._10,l._11,l._12,
  (if(l._13 == 1)  true else false),l._14,l._15,l._16,l._17,l._18,(if(l._19 == 1)  true else false))},
{(l:License) => Some(l.id,l.category,l.tool,l.supplier,l.manufacturer,l.licenseType,l.version_edition,
  l.location,l.keyContact,l.supplierContact,l.supportedBy,l.licenseEnd,(if(l.maintAgreement) 1 else 0),
  l.maintEnd,l.count,l.pricing,l.compatibility_notes,l.other_notes,(if(l.approved) 1 else 0))})

这不是理想的解决方案,但它有效并且比将我的案例类更改为 Int =] 更好。

【问题讨论】:

  • 有什么方法可以让 Slick 输出它试图发送到数据库的实际命令?大多数 SQL Server 人员无法对上述代码进行逆向工程,也无法知道 Slick 试图为您做什么。
  • @AaronBertrand 我不知道 Slick 是否有办法输出实际命令。我认为没有。
  • 请注意,在 mssql 中使用 slick-extensions 需要支付高昂的许可费用。我开始认为类型安全是邪恶的。
  • @JasonG 你在说什么?它是开源 BSD 许可证。编辑:没关系你在谈论版本 2.0.0。
  • 是的。对 DB2、Oracle 和现在的 MS SQL 的 Slick 支持将通过 Slick Extensions 遵循类型安全订阅协议。然而,Slick 本身并非如此。 slick.typesafe.com/doc/1.0.0/extensions.html

标签: sql-server scala slick


【解决方案1】:

SQLServer 不支持 ANSI 布尔数据类型。相反,它提供了一种 BIT 类型,它实际上是一种缺少布尔语义的数字数据类型(ANSI 声明布尔支持三个值truefalseunknown,当然还有null)。

鉴于之前的考虑,这不能归结为 Slick 的限制。

一个简单的解决方法是将布尔数据类型重新映射为数字类型,如果您的目标是开发多 DBMS 应用程序,您应该提供一个“工厂”层。

编辑(SQL 生成)

从生成的 SQL 中可以看出,

....
(not s25."approved")
....

应该是

....
(s25."approved" = 0)
....

手动尝试查询:它现在应该可以工作了。

【讨论】:

  • 我正在使用 BIT,但我很确定 Slick 会在 Scala 中将其转换为布尔值。我在应用程序的其他地方使用它,它的行为正确。只是不在过滤器中。
  • 您是否启用了调试跟踪以捕获 Slick 构建的 SQL 语句?
  • 如果您的意思是在服务器上,我不确定是否可以。我没有对服务器的完全访问权限。我只有编写应用程序所需的东西。除了在应用程序中的基本使用之外,我对数据库了解不多。
  • 我的意思是客户端:启用 Slick 日志记录会发出生成的 SQL
  • 我在为 Slick 启用日志记录时遇到了一些问题。真的没有文档。
猜你喜欢
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 2020-10-23
  • 1970-01-01
  • 2020-07-22
  • 2021-12-08
相关资源
最近更新 更多