簡體   English   中英

時間戳不兼容(NiFi 的 PutSQL)

[英]Timestamp incompatibility (NiFi's PutSQL)

我在使用 Nifi PutSQL 處理器將時間戳插入 PostgreSQL 數據庫時遇到了問題

更具體地說,當嘗試將 '2018-01-31T19:01:09+00:00' 格式的日期插入到時間戳列時,我收到以下錯誤消息:

2018-04-01 19:29:40,091 ERROR [Timer-Driven Process Thread-5] o.apache.nifi.processors.standard.PutSQL PutSQL[id=7997503a-0162-1000-ee81-a0361cad5e0c] Failed to update database for StandardFlowFileRecord[uuid=d02e8b39-e564-4c37-a08a-dab8931e9890,claim=StandardContentClaim [resourceClaim=StandardResourceClaim[id=1522615075930-15, container=default, section=15], offset=11492, length=163],offset=0,name=32836401373126,size=163] due to java.sql.SQLDataException: The value of the sql.args.5.value is '2018-01-31T20:19:35+00:00', which cannot be converted to a timestamp; routing to failure: java.sql.SQLDataException: The value of the sql.args.5.value is '2018-01-31T20:19:35+00:00', which cannot be converted to a timestamp
java.sql.SQLDataException: The value of the sql.args.5.value is '2018-01-31T20:19:35+00:00', which cannot be converted to a timestamp
    at org.apache.nifi.processors.standard.PutSQL.setParameters(PutSQL.java:711)
    at org.apache.nifi.processors.standard.PutSQL.lambda$null$5(PutSQL.java:313)
    at org.apache.nifi.processor.util.pattern.ExceptionHandler.execute(ExceptionHandler.java:127)
    at org.apache.nifi.processors.standard.PutSQL.lambda$new$6(PutSQL.java:311)
    at org.apache.nifi.processors.standard.PutSQL.lambda$new$9(PutSQL.java:354)
    at org.apache.nifi.processor.util.pattern.PutGroup.putFlowFiles(PutGroup.java:91)
    at org.apache.nifi.processor.util.pattern.Put.onTrigger(Put.java:101)
    at org.apache.nifi.processors.standard.PutSQL.lambda$onTrigger$20(PutSQL.java:574)
    at org.apache.nifi.processor.util.pattern.PartialFunctions.onTrigger(PartialFunctions.java:114)
    at org.apache.nifi.processor.util.pattern.RollbackOnFailure.onTrigger(RollbackOnFailure.java:184)
    at org.apache.nifi.processors.standard.PutSQL.onTrigger(PutSQL.java:574)
    at org.apache.nifi.controller.StandardProcessorNode.onTrigger(StandardProcessorNode.java:1122)
    at org.apache.nifi.controller.tasks.ContinuallyRunProcessorTask.call(ContinuallyRunProcessorTask.java:147)
    at org.apache.nifi.controller.tasks.ContinuallyRunProcessorTask.call(ContinuallyRunProcessorTask.java:47)
    at org.apache.nifi.controller.scheduling.TimerDrivenSchedulingAgent$1.run(TimerDrivenSchedulingAgent.java:128)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.text.ParseException: Unparseable date: "2018-01-31T20:19:35+00:00"
    at java.text.DateFormat.parse(DateFormat.java:366)
    at org.apache.nifi.processors.standard.PutSQL.setParameter(PutSQL.java:911)
    at org.apache.nifi.processors.standard.PutSQL.setParameters(PutSQL.java:707)
    ... 21 common frames omitted

我已經測試了從命令行將 '2018-01-31T19:01:09+00:00' 插入到 timestamptz 列中,它運行良好。 我嘗試了各種替代格式,例如:

  • '2018-01-31 19:01:09+00:00'
  • '2018-01-31 19:01:09+00'
  • '2018-01-31T19:01:09+00'
  • '2018-01-31 19:01:09'

它們在 Nifi 中都因相同的錯誤而失敗,即使它們在從命令行執行 INSERT 時都插入得很好。

請附上我的流程截圖。 如果您需要更多詳細信息,請告訴我。

NiFi流程的一部分

老實說,我更願意避免同時進行 java 轉換,因為將日期時間保留為字符串並將其直接插入到 Postgres DB 中效果很好。 我曾嘗試通過使用 UpdateAttribute 處理器來強制執行此操作,但這會導致其他錯誤。

我遇到了關於這個主題的各種問題,但我仍然不明白發生了什么。 最值得注意的是:

我通過使用 ExecuteStreamCommand 處理器解決了這個問題,該處理器調用 Python 腳本,該腳本將 JSON 行轉換為相應的 SQL 插入語句。 在這種情況下感興趣的表是reddit_post

python 腳本的代碼(我知道不需要INSERT參數,但這是因為我打算稍后添加一個UPDATE選項):

import json
import argparse
import sys

# For command line arguments
parser = argparse.ArgumentParser(description='Converts JSON to respective SQL statement')
parser.add_argument('statement_type', type=str, nargs=1)
parser.add_argument('table_name', type=str, nargs=1)

# Reading the command line arguments
statement_type = parser.parse_args().statement_type[0]
table_name = parser.parse_args().table_name[0]

# Initialize SQL statement 
statement = ''

for line in sys.stdin:
  # Load JSON line
  json_line = json.loads(line)

  # Add table name and SQL syntax
  if statement_type == 'INSERT':
    statement += 'INSERT INTO {} '.format(table_name)

  # Add table parameters and SQL syntax
  statement += '({}) '.format(', '.join(json_line.keys()))

  # Add table values and SQL syntax
  # Note that strings are formatted with single quotes, other data types are converted to strings (for the join method)
  statement += "VALUES ({});".format(', '.join("'{0}'".format(value.replace("'", "''")) if type(value) == str else str(value) for value in json_line.values()))

  # Send statement to stdout
  print(statement)
​

ExecuteStreamCommand 的配置(注意 Argument Delimeter 設置為單個空格): 在此處輸入圖片說明

流程片段:
在此處輸入圖片說明

我希望這可以幫助遇到類似問題的人。 如果您對如何改進腳本、流程或其他任何內容有任何建議,請隨時告訴我!

您可以在 PutSQL 之前使用 UpdateAttribute 以及toDate()format()表達式語言函數,將時間戳值轉換為數據庫可接受的值。

或者,您可以通過使用 PutDatabaseRecord 跳過 SplitText、ConvertJSONToSQL 和 PutSQL 步驟,您可以配置一個 RecordReader,它接受您的時間戳格式並進行相應的轉換。 如果可行,這是一個更好的解決方案,因為它將一次處理整個流文件(而不是單個行)

只需添加 3 位毫秒數就用 ExecuteSQL 處理器解決了我的問題 - “yyyy-mm-dd hh:mm:ss.sss”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM