如何将 "Lastname, Firstname" 数据拆分为单独的姓氏和名字列?
How can I split a "Lastname, Firstname" data into separate lastname and firstname columns?
我们有一个 table,其中有一列名为全名,格式为 "Lastname, Firstname"
我在 table 中添加了新列,这样我们就可以将姓氏和名字分开,但我不知道该怎么做。下面的代码是我使用的但是 "listFirst is not a recognized built-in function name."
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = listFirst(fullname, ","),
firstname = listRest(fullname, ", ")
</cfquery>
请指教。谢谢。
Listgetat
会成功,例如;
listgetat(fullname,1)
listgetat(fullname,2)
一个简单的方法(这不是最好的方法。但它看起来像一次性的东西。所以它应该没问题。)是 select 行作为一个单独的查询和循环更新每一行。此外,您还需要在将列表函数传递给查询之前对其进行评估。还使用 <cfqueryparam>
使字符串可以安全查询。
<cfquery name="splitname" datasource="dsn">
SELECT empID, fullname
FROM dbo.employees
</cfquery>
<cfloop query="splitname">
<cfquery datasource="dsn">
UPDATE dbo.employees
SET
lastname = <cfqueryparam value="#trim(listFirst(splitname.fullname, ","))#" cfsqltype="varchar">,
firstname = <cfqueryparam value="#trim(listlast(splitname.fullname, ","))#" cfsqltype="varchar">
WHERE empID = <cfqueryparam value="#splitname.empID#" cfsqltype="varchar">
</cfquery>
</cfloop>
我认为您的问题是您未能将 CF 函数放在 # 符号和引号中。
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = '#listFirst(fullname, ",")#'
, firstname = '#listRest(fullname, ", ")#'
</cfquery>
虽然你真的应该使用。
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = '<cfqueryparam cfsqltype="cf_sql_varchar"
value="#listFirst(fullname, ",")#">'
</cfquery>
作为最佳实践,我会在 SQL 语句之前清理变量并使用 trim 函数去除空格。
<cfscript>
firstname = trim(listFirst(fullname, ","));
lastname = trim(listLast(fullname, ","));
</cfscript>
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
firstname = '<cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">'
, lastname = '<cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">'
</cfquery>
此外,我们一直在尝试使用 SQL 的 DECLARE 语句来定义变量。这使得向您的 DBA 提供复杂查询并让他们能够快速处理它们变得非常容易。此外,许多查询多次使用相同的变量,因此将它们声明在列表顶部会更容易、更清晰。
<cfscript>
firstname = listFirst(fullname, ",");
lastname = listLast(fullname, ",");
</cfscript>
<cfquery name="splitname" datasource="dsn">
DECLARE @FirstName varchar(50) = <cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">
DECLARE @LastName varchar(50) = <cfqueryparam cfsqltype="cf_sql_varchar" value="#lastname#">
UPDATE dbo.employees
SET
firstname = @FirstName
, lastname = @LastName
</cfquery>
这不应该在 ColdFusion 中完成。这是数据问题,任何数据转换都应在 SQL 服务器本身上处理。无需将数据拉回 CF,让 CF 操作数据,然后将操作后的数据传回 SQL。
正如其他评论中提到的那样,您通过进行此更改打开了大量意想不到的蠕虫病毒。名称可能非常难以处理。
此答案基于以下事实:您的姓名数据由姓氏、逗号和姓名的其余部分组成。它将 trim 名字和姓氏并删除第一个逗号,但再次提防 Garbage In, Garbage Out.
.
您可以像这样将查询传递到 SQL:
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET lastname = ltrim(rtrim(left(fullname,charindex(',',fullname+',')-1)))
, firstname = ltrim(rtrim(substring(fullname,charindex(',',fullname+',')+1,len(fullname))))
</cfquery>
您可以在 https://dbfiddle.uk/?rdbms=sqlserver_2012&fiddle=85fc8abfdbb02c469e28c2e4dd1df4f5 的 SQL 中看到它。
除了 之外,没有人提到的一件重要事情是您可能对 CF 中的查询存在误解。如果不小心,可能会对数据库产生一些非常不愉快的后果。
能够混合使用 CFML 和 SQL 并不意味着您的数据库服务器执行 CFML 代码
数据库服务器对 CFML 一无所知。事实上,数据库服务器从未 看到 cfquery 中的任何 CFML 代码。所有 CFML (and/or cfcript) 代码都由 CF 应用程序服务器执行,甚至在数据库服务器进入画面之前。
那么,当您混合使用 CFML 和 SQL 时,实际会发生什么?从概念上讲,当代码执行时:
CF 服务器尝试评估任何 CF tags/functions 和
将它们转换为文字值。然后将这些值连接起来
与其余的纯文本 SQL,形成一个大的 SQL 字符串。
CF 然后将该SQL 字符串交给数据库执行
数据库服务器尝试执行 SQL 字符串和 returns 任何
结果到 CF 服务器
CF服务器将数据库结果转换成对象,比如
一个“查询”。
如您所见,两者绝对没有混淆。 CF 负责处理任何 CFML。数据库处理任何 SQL。永远不会相遇。
潜在的问题是什么?
进行这样的查询。它不会崩溃,但也不会产生预期的结果。
<cfset FORM.newAccountNumber = "1234,ABC">
<cfquery datasource="dsn">
UPDATE someTable
SET AccountNumber = '#listFirst(FORM.newValue, ",")#'
</cfquery>
实际情况是这样的。首先,CF 执行列表函数,其中 returns 文字字符串 "1234".
#listFirst(variables.newValue, ",")#
CF 然后将该文字插入 SQL 语句的其余部分,生成以下内容:
UPDATE someTable
SET AccountNumber = '1234'
当发送到数据库时,该语句将整个 table 中的 每个 个帐号设置为相同的值:“1234”。几乎可以肯定,这不是想要的结果。
了解 CFML 代码在查询中的解释方式有助于避免对数据库造成一些真正令人不快的后果。特别是如果您没有最近的备份...
我们有一个 table,其中有一列名为全名,格式为 "Lastname, Firstname"
我在 table 中添加了新列,这样我们就可以将姓氏和名字分开,但我不知道该怎么做。下面的代码是我使用的但是 "listFirst is not a recognized built-in function name."
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = listFirst(fullname, ","),
firstname = listRest(fullname, ", ")
</cfquery>
请指教。谢谢。
Listgetat
会成功,例如;
listgetat(fullname,1)
listgetat(fullname,2)
一个简单的方法(这不是最好的方法。但它看起来像一次性的东西。所以它应该没问题。)是 select 行作为一个单独的查询和循环更新每一行。此外,您还需要在将列表函数传递给查询之前对其进行评估。还使用 <cfqueryparam>
使字符串可以安全查询。
<cfquery name="splitname" datasource="dsn">
SELECT empID, fullname
FROM dbo.employees
</cfquery>
<cfloop query="splitname">
<cfquery datasource="dsn">
UPDATE dbo.employees
SET
lastname = <cfqueryparam value="#trim(listFirst(splitname.fullname, ","))#" cfsqltype="varchar">,
firstname = <cfqueryparam value="#trim(listlast(splitname.fullname, ","))#" cfsqltype="varchar">
WHERE empID = <cfqueryparam value="#splitname.empID#" cfsqltype="varchar">
</cfquery>
</cfloop>
我认为您的问题是您未能将 CF 函数放在 # 符号和引号中。
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = '#listFirst(fullname, ",")#'
, firstname = '#listRest(fullname, ", ")#'
</cfquery>
虽然你真的应该使用。
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
lastname = '<cfqueryparam cfsqltype="cf_sql_varchar"
value="#listFirst(fullname, ",")#">'
</cfquery>
作为最佳实践,我会在 SQL 语句之前清理变量并使用 trim 函数去除空格。
<cfscript>
firstname = trim(listFirst(fullname, ","));
lastname = trim(listLast(fullname, ","));
</cfscript>
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
firstname = '<cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">'
, lastname = '<cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">'
</cfquery>
此外,我们一直在尝试使用 SQL 的 DECLARE 语句来定义变量。这使得向您的 DBA 提供复杂查询并让他们能够快速处理它们变得非常容易。此外,许多查询多次使用相同的变量,因此将它们声明在列表顶部会更容易、更清晰。
<cfscript>
firstname = listFirst(fullname, ",");
lastname = listLast(fullname, ",");
</cfscript>
<cfquery name="splitname" datasource="dsn">
DECLARE @FirstName varchar(50) = <cfqueryparam cfsqltype="cf_sql_varchar" value="#firstname#">
DECLARE @LastName varchar(50) = <cfqueryparam cfsqltype="cf_sql_varchar" value="#lastname#">
UPDATE dbo.employees
SET
firstname = @FirstName
, lastname = @LastName
</cfquery>
这不应该在 ColdFusion 中完成。这是数据问题,任何数据转换都应在 SQL 服务器本身上处理。无需将数据拉回 CF,让 CF 操作数据,然后将操作后的数据传回 SQL。
正如其他评论中提到的那样,您通过进行此更改打开了大量意想不到的蠕虫病毒。名称可能非常难以处理。
此答案基于以下事实:您的姓名数据由姓氏、逗号和姓名的其余部分组成。它将 trim 名字和姓氏并删除第一个逗号,但再次提防 Garbage In, Garbage Out.
.
您可以像这样将查询传递到 SQL:
<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET lastname = ltrim(rtrim(left(fullname,charindex(',',fullname+',')-1)))
, firstname = ltrim(rtrim(substring(fullname,charindex(',',fullname+',')+1,len(fullname))))
</cfquery>
您可以在 https://dbfiddle.uk/?rdbms=sqlserver_2012&fiddle=85fc8abfdbb02c469e28c2e4dd1df4f5 的 SQL 中看到它。
除了
能够混合使用 CFML 和 SQL 并不意味着您的数据库服务器执行 CFML 代码
数据库服务器对 CFML 一无所知。事实上,数据库服务器从未 看到 cfquery 中的任何 CFML 代码。所有 CFML (and/or cfcript) 代码都由 CF 应用程序服务器执行,甚至在数据库服务器进入画面之前。
那么,当您混合使用 CFML 和 SQL 时,实际会发生什么?从概念上讲,当代码执行时:
CF 服务器尝试评估任何 CF tags/functions 和 将它们转换为文字值。然后将这些值连接起来 与其余的纯文本 SQL,形成一个大的 SQL 字符串。
CF 然后将该SQL 字符串交给数据库执行
数据库服务器尝试执行 SQL 字符串和 returns 任何 结果到 CF 服务器
CF服务器将数据库结果转换成对象,比如 一个“查询”。
如您所见,两者绝对没有混淆。 CF 负责处理任何 CFML。数据库处理任何 SQL。永远不会相遇。
潜在的问题是什么?
进行这样的查询。它不会崩溃,但也不会产生预期的结果。
<cfset FORM.newAccountNumber = "1234,ABC">
<cfquery datasource="dsn">
UPDATE someTable
SET AccountNumber = '#listFirst(FORM.newValue, ",")#'
</cfquery>
实际情况是这样的。首先,CF 执行列表函数,其中 returns 文字字符串 "1234".
#listFirst(variables.newValue, ",")#
CF 然后将该文字插入 SQL 语句的其余部分,生成以下内容:
UPDATE someTable
SET AccountNumber = '1234'
当发送到数据库时,该语句将整个 table 中的 每个 个帐号设置为相同的值:“1234”。几乎可以肯定,这不是想要的结果。
了解 CFML 代码在查询中的解释方式有助于避免对数据库造成一些真正令人不快的后果。特别是如果您没有最近的备份...