Как разделить данные «Фамилия, Имя» на отдельные столбцы «Фамилия» и «Имя»? - PullRequest
0 голосов
/ 21 декабря 2018

У нас есть таблица со столбцом с именем fullname в формате «Фамилия, Имя»

Я добавил новые столбцы в таблицу, чтобы мы могли разделить фамилию и имя, но я не могу понятькак это сделать.Ниже приведен код, который я использовал, но «listFirst не является распознанным именем встроенной функции».

<cfquery name="splitname" datasource="dsn">
UPDATE dbo.employees
SET
  lastname = listFirst(fullname, ","),
  firstname = listRest(fullname, ", ")
</cfquery>

Пожалуйста, сообщите.Спасибо.

Ответы [ 5 ]

0 голосов
/ 22 декабря 2018

В дополнение к ответу Шона , одна важная вещь, о которой никто не упомянул, это то, что вы, возможно, работаете из-за неправильного представления о запросах в CF.Тот, который потенциально может иметь некоторые очень неприятные последствия для базы данных, если не быть осторожным.

Возможность смешивать CFML и SQL не означает, что ваш сервер баз данных выполняет код CFML

Серверы баз данных ничего не знают о CFML.Фактически, сервер базы данных даже не видит какого-либо CFML-кода в cfquery.Весь код CFML (и / или cfcript) выполняется сервером приложений CF еще до того, как сервер базы данных входит в изображение.

Так что же на самом деле происходит, когда вы смешиваете CFML и SQL?Концептуально, когда код выполняется:

  1. Сервер CF пытается оценить любые теги / функции CF и преобразовать их в литеральные значения.Эти значения затем объединяются с остальной частью обычного текста SQL, чтобы сформировать одну большую строку SQL.

  2. CF затем передает эту строку SQL в базу данных для выполнения

  3. Сервер базы данных пытается выполнить строку SQL и возвращает любые результаты на сервер CF
  4. Сервер CF преобразует результаты базы данных в объекты, например «Query».

Итак, как вы можете видеть, нет абсолютно никакого смешения двух.CF выполняет свою работу по обработке любого CFML.База данных обрабатывает любой SQL.Никогда не встретимся между ними.

В чем потенциальная проблема?

Возьмите такой запрос.Он не рухнет, но и не даст ожидаемого результата.

<cfset FORM.newAccountNumber = "1234,ABC">

<cfquery datasource="dsn">
   UPDATE someTable
   SET    AccountNumber = '#listFirst(FORM.newValue, ",")#'
</cfquery>

Что на самом деле происходит, так это.Во-первых, CF выполняет функцию списка, которая возвращает буквенную строку «1234».

   #listFirst(variables.newValue, ",")#

CF затем вставляет этот литерал в остальную часть оператора SQL, создавая следующее:

    UPDATE someTable
    SET    AccountNumber = '1234'

При отправке в базу данных этот оператор устанавливает каждые один номер счета во всей таблице с тем же значением: «1234».Почти наверняка, не желаемый результат.

Понимание того, как код CFML интерпретируется в запросах, может помочь избежать некоторых действительно неприятных последствий для вашей базы данных.Особенно, если у вас нет последних резервных копий ...

0 голосов
/ 22 декабря 2018

Это не должно быть сделано в ColdFusion.Это проблема с данными, и любые преобразования данных должны обрабатываться на самом SQL Server.Нет необходимости возвращать данные обратно в CF, заставлять CF манипулировать данными, а затем передавать манипулированные данные обратно в SQL.

И, как уже упоминалось в других комментариях, вы открываете огромную банку непреднамеренных червей, внося эти изменения.Имена могут быть невероятно сложными для работы.

Этот ответ основан на том факте, что данные вашего имени состоят из фамилии, за которой следует запятая, а за ней - остальная часть имени.Он обрезает имена и фамилии и удаляет первую запятую, но опять-таки с осторожностью относитесь к 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>

Выможно увидеть это в SQL на https://dbfiddle.uk/?rdbms=sqlserver_2012&fiddle=85fc8abfdbb02c469e28c2e4dd1df4f5.

0 голосов
/ 21 декабря 2018

Один простой способ (это не самый лучший способ сделать это. Но это выглядит как разовая вещь. Так что должно быть хорошо.) - это выбрать строки как отдельный запрос и обновить каждую строку в цикле.,Также вам нужно будет оценить функции списка, прежде чем передавать их в запрос.Также используйте <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>
0 голосов
/ 21 декабря 2018

Я думаю, что ваша проблема в том, что вы не смогли поместить свои функции 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 и использовал бы функцию обрезки, чтобы избавиться от пробелов.

<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 для определения переменных там.Это позволяет очень просто задавать сложные запросы вашему администратору баз данных и иметь возможность быстро с ними работать.Кроме того, многие запросы используют одни и те же переменные несколько раз, поэтому намного проще и понятнее объявить их в верхней части списка.

<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>
0 голосов
/ 21 декабря 2018

Listgetat добьется цели, например;

listgetat(fullname,1)  
listgetat(fullname,2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...