简体   繁体   English

如何创建Anorm查询以跳过更新DB中的None值(Scala)

[英]How to create Anorm query to skip updating None values in DB (Scala)

I am using Anorm (2.5.1) in my Play+Scala application (2.5.x, 2.11.11). 我在Play + Scala应用程序(2.5.x,2.11.11)中使用了Anorm(2.5.1)。 I keep facing the issue quite often where if the case class argument value is None, I don't want that parameter value to be inserted/updated in SQL DB. 我经常遇到这个问题,如果case类参数值为None,我不希望在SQL DB中插入/更新该参数值。 For example: 例如:

case class EditableUser(
    user_pk: String,
    country: Option[String],
    country_phone_code: Option[Int],
    phonenumber: Option[String],
    emailid: Option[String],
    format_all: Option[String]
)
....
val eUser: EditableUser = EditableUser("PK0001", None, None, None, Some("xyz@email.com"), Some("yes"))
...
    SQL"""
       update #$USR SET
       COUNTRY=${eUser.country},
       COUNTRY_PHONE_CODE=${eUser.country_phone_code},
       PHONENUMBER=${eUser.phonenumber},
       EMAILID=${emailid},
       FORMAT_ALL=${format_all}
       where (lower(USER_PK)=lower(${eUser.user_pk}))
    """.execute()

Here when the value is None, Anorm will insert 'null' into corresponding column in SQL DB. 在此,当值为None时,Anorm将在SQL DB中的相应列中插入“ null”。 Instead I want to write the query in such a way that Anorm skips updating those values which are None ie does not overwrite. 相反,我想以这样的方式编写查询,即Anorm跳过更新那些值为None(即不覆盖)的值。

You should use boundStatements/preparedStatement and while setting values for the query don't set the values for the columns which are none. 您应该使用boundStatements / preparedStatement,而为查询设置值时不要为没有设置的列设置值。

For example 例如

SQL(
  """
select * from Country c 
join CountryLanguage l on l.CountryCode = c.Code 
where c.code = {countryCode};
  """
).on("countryCode" -> "FRA")

Or in your case: 或您的情况:

import play.api.db.DB
import anorm._

val stat = DB.withConnection(implicit c =>
  SQL("SELECT name, email FROM user WHERE id={id}").on("id" -> 42)
)

While writing you your query you check if the value you are going to put in on(x->something) is not None if it's nice don't put it hence you will not update the values which are none. 在编写查询时,您检查要放在on(x-> something)上的值是否不为None(如果可以的话)请不要输入,因此不会更新为none的值。

Without the ability (or library) to access the attribute names themselves, it would still be possible, if slightly clunky in some circles, to build the update statement dynamically depending on the values that are present in the case class: 如果没有能力(或库)本身访问属性名称,则即使在某些情况下有些笨拙,仍然有可能根据case类中存在的值动态地构建更新语句:

case class Foo(name:String, age:Option[Int], heightCm:Option[Int])
...
def phrase(k:String,v:Option[Int]):String=if (v.isDefined) s", $k={$k}" else ""

def update(foo:Foo) : Either[String, Foo] = DB.withConnection { implicit c =>
  def stmt(foo:Foo) = "update foo set "+
    //-- non option fields
    "name={name}" +
    //-- option fields
    phrase("age", foo.age) +
    phrase("heightCm", foo.heightCm)

  SQL(stmt(foo))
    .on('name -> name, 'age -> age, 'heightCm -> heightCm)
    .executeUpdate()

The symbols that are not present in the actual submitted SQL can still be specified in the on . 仍可以在on指定实际提交的SQL中不存在的符号。 Catering for other data types also needed. 还需要迎合其他数据类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM