为什么在通过 Powershell 向 Oracle 数据库插入时,尖音符号与其基本字母分开?
Why does the acute gets separated from its base letter when making an insert to an oracle database via Powershell?
我正在使用 Powershell 执行插入语句并将字符串插入数据库 table。我要插入的文本是从 HTTP 请求到 Confluence 的 REST API 并包含捷克语字符。以下代码片段完成将数据插入数据库的工作
$DAOControllerClass | Add-member -MemberType ScriptMethod -Name Get-DataBaseConnection -Value {
[OutputType([System.Data.OracleClient.OracleConnection])]
$username = $this.username
$password = $this.password
$data_source = $this.data_source
log("Executing Get-DataBaseConnection")
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
try {
$con.Open()
} catch {
throw "Could not open database connection"
}
log("Connectiong opened")
return $con
}
$DAOControllerClass | Add-Member -MemberType ScriptMethod -Name Update-CNFLPageIntoOldWorld -Value {
param(
[Parameter(Mandatory=$true)][String[]]$values
)
log("Executing Update-CNFLPageIntoBaseLayer")
try{
$con = $this.'Get-DataBaseConnection'()
$command = $con.CreateCommand()
$command.Connection = $con
$command.CommandText = [IO.File]::ReadAllText(".\Database queries\Data dictionary - Core layer queries\Update_cnfl_page_old_world.sql")
$null = $command.Parameters.Add("cnfl_page_id", $values[0])
$null = $command.Parameters.Add("label", $values[1])
$null = $command.Parameters.Add("business_pojem_html", $values[2])
$null = $command.Parameters.Add("popis_html",$values[3]) # The issue is with $values[3]
$null = $command.ExecuteNonQuery()
log("The cnfl page with the id: " + $values[0] + " got updated in the table confluence_page_old_world")
} catch {
throw (“Database Exception: " + $con.ConnectionString + ": " + $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) {
$con.close()
$command.Dispose()
}
}
}
现在我从 Confluence 页面下载时作为参数传递的文本如下:"Reportingové statusy a příchody/odchody klientů."
当我在 Powershell 中打印此文本时,一切看起来都很好。所有字母均按应有的方式表示。
当我调试此代码并查看分配给 $command.CommandText 的文本时,它看起来也不错。
但是当我在数据库中看到结果时,它看起来如下所示:
所以所有的字母都很好,除了尖音符从它的基本字母中分离出来。我在 powershell 中尝试了不同的编码,我试图更改数据库中的 NLS 设置。我还尝试写入 .txt 文件,使用 utf-8、unicode 和 ISO/IEC 8859-2 对其进行编码,只是为了从文件中读取它,但这也没有用。
唯一可行的是当我像这样将文本硬编码到 Powershell 中时:
$null = $command.Parameters.Add("popis_html","Reportingové statusy a příchody/odchody klientů.")
然后我得到了预期的结果。所以在我看来,当将字符串作为参数传递时,一些转换或编码正在发生,但我不知道它可能是什么,因为字母实际上得到了表示,它只是关于尖音符号。我在 Powershell
中有以下编码设置
IsSingleByte : True
BodyName : iso-8859-2
EncodingName : Central European (Windows)
HeaderName : windows-1250
WebName : windows-1250
WindowsCodePage : 1250
IsBrowserDisplay : True
IsBrowserSave : True
IsMailNewsDisplay : True
IsMailNewsSave : True
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 1250
以及以下 nls_session_parameters
NLS_LANGUAGE CZECH
NLS_TERRITORY CZECH REPUBLIC
NLS_CURRENCY Kč
NLS_ISO_CURRENCY CZECH REPUBLIC
NLS_NUMERIC_CHARACTERS ,.
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD.MM.RR
NLS_DATE_LANGUAGE CZECH
NLS_SORT CZECH
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD.MM.RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD.MM.RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY Kč
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
我尝试使用此行将 Powershell 编码设置为 Unicode
$OutputEncoding = [System.Text.Encoding]::Unicode
数据库中的结果是一样的。我还能尝试什么?
谢谢!
可能问题如下(本人无法验证):
听起来您从 Confluence REST API 收到的 字符串 分解 Unicode normalization form (NFD), in which accented characters are represented by two code points: the base letter (e.g., e
), followed by a combining diacritic (e.g., ́
, the combining acute accent, U+0301
)
而且看起来 Oracle 也许 在这个 decomposed 范式上有问题并且只支持 组合形式(NFC),其中重音字母直接表示为单个代码点(例如,é
,the Latin small letter with acute, U+00E9
),
因此,您可以尝试使用String.Normalize()
method将字符串转换为组合形式(NFC):
$values[3].Normalize() # Converts string $values[3] to NFC
我正在使用 Powershell 执行插入语句并将字符串插入数据库 table。我要插入的文本是从 HTTP 请求到 Confluence 的 REST API 并包含捷克语字符。以下代码片段完成将数据插入数据库的工作
$DAOControllerClass | Add-member -MemberType ScriptMethod -Name Get-DataBaseConnection -Value {
[OutputType([System.Data.OracleClient.OracleConnection])]
$username = $this.username
$password = $this.password
$data_source = $this.data_source
log("Executing Get-DataBaseConnection")
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
try {
$con.Open()
} catch {
throw "Could not open database connection"
}
log("Connectiong opened")
return $con
}
$DAOControllerClass | Add-Member -MemberType ScriptMethod -Name Update-CNFLPageIntoOldWorld -Value {
param(
[Parameter(Mandatory=$true)][String[]]$values
)
log("Executing Update-CNFLPageIntoBaseLayer")
try{
$con = $this.'Get-DataBaseConnection'()
$command = $con.CreateCommand()
$command.Connection = $con
$command.CommandText = [IO.File]::ReadAllText(".\Database queries\Data dictionary - Core layer queries\Update_cnfl_page_old_world.sql")
$null = $command.Parameters.Add("cnfl_page_id", $values[0])
$null = $command.Parameters.Add("label", $values[1])
$null = $command.Parameters.Add("business_pojem_html", $values[2])
$null = $command.Parameters.Add("popis_html",$values[3]) # The issue is with $values[3]
$null = $command.ExecuteNonQuery()
log("The cnfl page with the id: " + $values[0] + " got updated in the table confluence_page_old_world")
} catch {
throw (“Database Exception: " + $con.ConnectionString + ": " + $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) {
$con.close()
$command.Dispose()
}
}
}
现在我从 Confluence 页面下载时作为参数传递的文本如下:"Reportingové statusy a příchody/odchody klientů."
当我在 Powershell 中打印此文本时,一切看起来都很好。所有字母均按应有的方式表示。 当我调试此代码并查看分配给 $command.CommandText 的文本时,它看起来也不错。
但是当我在数据库中看到结果时,它看起来如下所示:
所以所有的字母都很好,除了尖音符从它的基本字母中分离出来。我在 powershell 中尝试了不同的编码,我试图更改数据库中的 NLS 设置。我还尝试写入 .txt 文件,使用 utf-8、unicode 和 ISO/IEC 8859-2 对其进行编码,只是为了从文件中读取它,但这也没有用。
唯一可行的是当我像这样将文本硬编码到 Powershell 中时:
$null = $command.Parameters.Add("popis_html","Reportingové statusy a příchody/odchody klientů.")
然后我得到了预期的结果。所以在我看来,当将字符串作为参数传递时,一些转换或编码正在发生,但我不知道它可能是什么,因为字母实际上得到了表示,它只是关于尖音符号。我在 Powershell
中有以下编码设置IsSingleByte : True
BodyName : iso-8859-2
EncodingName : Central European (Windows)
HeaderName : windows-1250
WebName : windows-1250
WindowsCodePage : 1250
IsBrowserDisplay : True
IsBrowserSave : True
IsMailNewsDisplay : True
IsMailNewsSave : True
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 1250
以及以下 nls_session_parameters
NLS_LANGUAGE CZECH
NLS_TERRITORY CZECH REPUBLIC
NLS_CURRENCY Kč
NLS_ISO_CURRENCY CZECH REPUBLIC
NLS_NUMERIC_CHARACTERS ,.
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD.MM.RR
NLS_DATE_LANGUAGE CZECH
NLS_SORT CZECH
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD.MM.RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD.MM.RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY Kč
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
我尝试使用此行将 Powershell 编码设置为 Unicode
$OutputEncoding = [System.Text.Encoding]::Unicode
数据库中的结果是一样的。我还能尝试什么? 谢谢!
可能问题如下(本人无法验证):
听起来您从 Confluence REST API 收到的 字符串 分解 Unicode normalization form (NFD), in which accented characters are represented by two code points: the base letter (e.g., e
), followed by a combining diacritic (e.g., ́
, the combining acute accent, U+0301
)
而且看起来 Oracle 也许 在这个 decomposed 范式上有问题并且只支持 组合形式(NFC),其中重音字母直接表示为单个代码点(例如,é
,the Latin small letter with acute, U+00E9
),
因此,您可以尝试使用String.Normalize()
method将字符串转换为组合形式(NFC):
$values[3].Normalize() # Converts string $values[3] to NFC