Я пытаюсь опубликовать файл csv, который в настоящее время хранится в репозитории Azure, и хотел бы вставить содержимое csv в базу данных SQL Azure с помощью конвейера выпуска. Технически это осуществимо? Поскольку я продолжаю нажимать «Код ошибки операционной системы 997 (выполняется операция перекрывающегося ввода-вывода.)». ошибка.
Пример данных CSV:
"True", "123,234325", "abc"
Вот скрипт, который я использовал:
Bulk Insert TargetTableName
from 'ArtifactAlias\foldername\filename.csv'
with
(
FIRSTROW = 2,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
FIELDQUOTE = '"'
)
Да, это технически осуществимо. Какой фрагмент кода вызывает эту ошибку? Используете ли вы самостоятельное размещение или конвейеры Azure?
@Nick.Mc, я использую Azure Pipelines. Согласно журналу развертывания, в нем не указано, какая часть кода вызывает эту ошибку. На самом деле, я также тестировал вставку CSV-файла из локальной версии в ту же базу данных SQL Azure через SSMS. показывает ту же ошибку.
@Dai, я дополнил скрипт. Спасибо.
Сможете ли вы запустить этот сценарий без использования конвейеров? Похоже, вам нужно запустить этот сценарий на сервере SQL, а не на других машинах, таких как агенты конвейера. Информацию смотрите здесь.
@AlvinZhao-MSFT, я пытался запустить его в SSMS. Выдает ту же ошибку.
Вероятно, нам нужно найти другие варианты, такие как инструмент bcp.
@AlvinZhao-MSFT, я тоже исследовал bcp. Однако мой файл csv содержит текстовый квалификатор, а bcp не предоставляет этот аргумент. Вся история усложнится.
Это действительно сложнее. Можете ли вы предоставить образец содержимого CSV, чтобы объяснить ваши требования? Кстати, Azure Pipelines — это всего лишь тип инструмента автоматизации. Если вы не можете использовать этот инструмент локально, он, вероятно, выйдет из строя в конвейерах. Вы можете отредактировать исходное сообщение с учетом всех требований, чтобы воспользоваться идеями экспертов сообщества.
@akaya_1992, я обновил ответ, чтобы экспортировать ожидаемое содержимое в новый файл csv во время задания агента конвейера и использовать его для запуска команды bcp
. Надеюсь, что он сможет решить ваш вопрос в этом посте. Спасибо за обмен и усилия.
В соответствии с вашим дополнением и вашим возможным требованием защитить ,
, который можно использовать в каждом поле вашего содержимого CSV, я бы предложил запустить приведенный ниже сценарий PowerShell во время работы агента, чтобы создать новый файл CSV без заголовков, где ваш текущий разделитель (,
) меняется на другой (|
в моем случае), который не будет конфликтовать с данными в полях; это также изменит поле True/False на 1/0 для импорта.
Таблица образцов
CREATE TABLE [dbo].[SampleTable] (
[IsTrueFalse] BIT NOT NULL,
[Number] NVARCHAR(50) NOT NULL,
[Remark] NVARCHAR(50) NOT NULL
);
образец.csv
IsTrueFalse,Number,Remark
"True", "123,234325", "abc"
"False", "456,567890", "efg"
noheaders.csv
1| 123,234325| abc
0| 456,567890| efg
Скрипт PowerShell, используемый в конвейере выпуска
# Define file paths
$inputFile = "$(System.DefaultWorkingDirectory)\_azuresql\sample.csv"
$outputFile = "$(System.DefaultWorkingDirectory)\_azuresql\noheaders.csv"
# Read the input file content
$content = Get-Content $inputFile
# Process each line: replace `",` with `|`, remove quotes, and convert "True"/"False" to 1/0
$content | Select-Object -Skip 1 | ForEach-Object {
# Replace `",` with `|` and then remove all remaining quotes
$line = $_ -replace '",', '|' -replace '"', ''
# Convert "True"/"False" to 1/0 for the IsTrueFalse column
$fields = $line -split '\|'
$fields[0] = if ($fields[0] -eq 'True') { '1' } elseif ($fields[0] -eq 'False') { '0' } else { $fields[0] }
$fields -join '|'
} | Set-Content $outputFile
echo "Checking the contents of $outputFile..."
Get-Content $outputFile
echo "Checking bcp version..."
bcp -v
echo "Running bcp command..."
bcp SampleTable in "$outputFile" -S $(AzureSQLServer) -d $(AzureSQLDB) -U $(AzureSQLServerAdmin) -P $(AzureSQLServerAdminPWD) -q -c -t "|" # Pipe delimiter
Из выражения FIRSTROW = 2
вашего SQL-скрипта я увидел, что ваш CSV-файл должен иметь первую строку заголовков. Для этого вы можете удалить первую строку и вывести ожидаемое содержимое в новый файл во время задания агента конвейера. Вот обновленный сценарий PowerShell для справки.
# Define file paths
$inputFile = "$(System.DefaultWorkingDirectory)\_azuresql\test.csv"
$outputFile = "$(System.DefaultWorkingDirectory)\_azuresql\noheaders.csv"
# Read the input CSV file, skip the first line (header), and write the result to the output file
Get-Content $inputFile | Select-Object -Skip 1 | Set-Content $outputFile
echo "Checking bcp version..."
bcp -v
echo "Running bcp command..."
bcp Users in "$outputFile" -S $(AzureSQLServer) -d $(AzureSQLDB) -U $(AzureSQLServerAdmin) -P $(AzureSQLServerAdminPWD) -q -c -t ","
Судя по вашему описанию, похоже, что вам нужно запустить SQL-скрипт на SQL, а не на машине агента конвейера, как обсуждалось в этой теме.
В соответствии с этим документом о том, как загрузить данные из CSV-файла в базу данных (bcp) — Azure SQL | Microsoft Learn, мы могли бы использовать инструмент BCP для импорта содержимого CSV в таблицу базы данных SQL Azure.
Следуя этому направлению, я протестировал пример конвейера выпуска, работающего на агенте windows-latest
, размещенном в Microsoft, и сумел импортировать содержимое CSV-файла.
Added a test.csv
file in my repo with the contents like below;
In a release pipeline, added the repo as artifacts and ran the PowerShell script;
echo "Checking bcp version..."
bcp -v
echo "Running bcp command..."
bcp Users in "$(System.DefaultWorkingDirectory)/_azuresql/test.csv" -S
$(AzureSQLServer) -d $(AzureSQLDB) -U $(AzureSQLServerAdmin) -P
$(AzureSQLServerAdminPWD) -q -c -t ","
As the release was succeeded, we could check the update in the table;
Привет @Alvin Zhao, очень благодарен за твою помощь~ Могу ли я узнать, тестировали ли вы также файл csv, имеющий текстовый квалификатор?
Я не совсем понимаю, что вы имеете в виду под текстовым квалификатором. Можете ли вы поделиться образцом в исходном посте? Спасибо.
без проблем. дополнено.
@akaya_1992, смотрите мой обновленный ответ в соответствии с вашим дополнением.
Чжао, мне удалось получить тот же результат, добавив этап запуска сценария Python, но я все равно ценю ваши большие усилия в этом направлении.
Нам нужно больше подробностей…