PDA

Показать полную графическую версию : [решено] Преобразовать данные в DataTable


Griboed0ff
15-03-2022, 14:59
Доброго времени суток! Делаю запросы в базу через консольную утилиту sqlcl и пытаюсь привести ответ в нужную форму. А именно, в ответ от утилиты получаю System.Array с объектами. К объектам можно обратиться по индексу, но проблема в том, что PowerShell распознает разбивку на объекты неправильно. В ответе есть значение таблицы, которое содержит много строк и PowerShell каждую строку помечает как отдельный объект. В ответе два столбца и строки. Первая строка в ответах всегда пустая.
Пример вывода csv, System.Array, count 8:

"COUNT_ERROR","BODY_ERROR"
10412,"ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.WebException: The remote serve
r returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'"
25,"ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.WebException: The remote server r
eturned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'"
Пример вывода xml, System.Array, count 16:

<?xml version='1.0' encoding='UTF-8' ?>
<RESULTS>
<ROW>
<COLUMN NAME="COUNT_ERROR"><![CDATA[10513]]></COLUMN>
<COLUMN NAME="BODY_ERROR"><![CDATA[ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.
WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718']]></COLUMN>
</ROW>
<ROW>
<COLUMN NAME="COUNT_ERROR"><![CDATA[26]]></COLUMN>
<COLUMN NAME="BODY_ERROR"><![CDATA[ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.
WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718']]></COLUMN>
</ROW>
</RESULTS>
Пример вывода json, System.Array, count 6:{"results":[{"columns":[{"name":"COUNT_ERROR","type":"NUMBER"},{"name":"BODY_ERROR","type":"VARCHAR2"}],"items":
[
{"count_error":10579,"body_error":"ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.We
bException: The remote server returned an error: (400) Bad Request.\r\n at System.Net.HttpWebRequest.GetResponse()\r\n at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'"}
,{"count_error":27,"body_error":"ERROR:МTC:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера МТС. Exception=System.Net.WebE
xception: The remote server returned an error: (500) Internal Server Error.\r\n at System.Net.HttpWebRequest.GetResponse()\r\n at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'"}
]}]}
Далее это добро я хочу записать в другую базу, где есть эти же два столбца. Для этого мне нужно правильно распознать получаемые данные, а это два столбца и сколько то строк. Данные преобразовать в DataTable. Воспользоваться Invoke-SQLiteBulkCopy.
Не могу никак разобрать данные и преобразовать в DataTable.

Griboed0ff
15-03-2022, 21:27
Пока только получилось сохранить данные в файл csv и после импорта уже разбирать его.
$datasource = "D:\base_dw.db"
$file = "D:\123.csv"
[string]$time= "Table_" + [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds

$comand = @"
drop table qqqqqqq;
create global temporary table qqqqqqq
( ncount number,
rerror varchar (1000))
on commit delete rows;
DECLARE
rrrr rta.list.request_id%TYPE;
begin
dbms_output.enable (buffer_size => NULL);
FOR jj IN (select distinct result_detail from rta.list where system_date>='16.02.2022' and operation_error='ERROR')
loop
select count(result_detail) into rrrr from rta.list where result_detail=jj.result_detail and system_date>='16.02.2022';
Insert into qqqqqqq(ncount,rerror) values (rrrr,jj.result_detail);
--dbms_output.put_line(rrrr||'::::'||jj.result_detail);
end loop;
end;
/
select * from qqqqqqq;
"@


$comand | D:\sqlcl\bin\sql.exe -silent -oci **** | Where {$_} |Out-File $file

# Создаем столбцы и указываем типы данных
$table = New-Object system.Data.DataTable 'TestDataTable1'
$newcol = New-Object system.Data.DataColumn SYSDATETIME,([datetime]);
$table.columns.add($newcol)
$newcol = New-Object system.Data.DataColumn COUNT_ERROR,([int]);
$table.columns.add($newcol)
$newcol = New-Object system.Data.DataColumn BODY_ERROR,([string]);
$table.columns.add($newcol)


# Записываем инфу в ранее созданные столбцы из CSV
$csv = Import-CSV $file -delimiter ","
$csv | ForEach-Object {
$row = $table.NewRow()
$row.SYSDATETIME= (get-date).ToString() #('HH:00:00')
$row.COUNT_ERROR= ($_.COUNT_ERROR)
$row.BODY_ERROR= ($_.BODY_ERROR)
$table.Rows.Add($row) }

Invoke-SQLiteBulkCopy -DataTable $table -DataSource $DataSource -Table "count_error" -force
Может кто знает как можно обойтись без экспорта и импорта файла? Решить все в теле скрипта?

Sham
15-03-2022, 22:24
есть ConvertFrom-Csv. Можно попробовать через переменную.
$arr = $comand .... (без Out-File)
$csv = $arr -join "`r`n" | ConvertFrom-Csv -Delimiter ','

Griboed0ff
16-03-2022, 07:23
Я ранее пробовал ConvertTo-Csv, но всегда получал, что-то типа:
"Length"
"40"
"291"
"45"
"211"
"301"
"45"
"209"
А до этого пытался сохранить xml и разобрать его, но он не так прост оказался.
$arr -join "`r`n" | ConvertFrom-Csv -Delimiter ',' »
Не понял что за магия с джоинами, но работает! Спасибо!

Griboed0ff
16-03-2022, 09:42
Осталось победить кодировку. Она ломается два раза, сначала при выгрузке из одной базы, а потом уже после загрузки в другую. В самом PL/SQL Developer все круто, но консольные утилиты все ломают.
Что изначально:
ERROR:РТТ:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception при чтении ответа сервера РТТ. Exception=System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'
После получения данных в PowerShell:
ERROR:РњTТ:StatusLastOperation=RequestError Подробная ошибка=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception РїСЂРё чтении ответа сервера РњРўРЎ. Exception=System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'
В итоговой базе:
ERROR:╨ЬTТ:StatusLastOperation=RequestError ╨Я╨╛╨┤╤А╨╛╨▒╨╜╨░╤П ╨╛╤И╨╕╨▒╨║╨░=' ERROR: StatusLastOperation=ErrorReadingStreamException Exception ╨┐╤А╨╕ ╤З╤В╨╡╨╜╨╕╨╕ ╨╛╤В╨▓╨╡╤В╨░ ╤Б╨╡╤А╨▓╨╡╤А╨░ ╨Ь╨в╨б. Exception=System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at SecureHttp.SecureHttpRequest.PostHttpData(String url, String postData, X509Certificate2 certificate) in y:\HttpRequest.cs:line 718'

Griboed0ff
16-03-2022, 12:27
Кодировка побеждена function ConvertTo-Encoding ([string]$From, [string]$To){
Begin{
$encFrom = [System.Text.Encoding]::GetEncoding($from)
$encTo = [System.Text.Encoding]::GetEncoding($to)
}
Process{
$bytes = $encTo.GetBytes($_)
$bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes)
$encTo.GetString($bytes)
}
}
В ISE $arr = $comand ....| ConvertTo-Encoding UTF-8 windows-1251
В консоли $arr = $comand ....| ConvertTo-Encoding UTF-8 cp866

Sham
16-03-2022, 18:36
что за магия с джоинами »
Сами же пишите, что изначально в массиве неправильный csv. Чтобы правильно распарсить csv-строки по объектам ему нужен исходный текст целиком с переносами строк.




© OSzone.net 2001-2012