SQL Server 2005 - вставка записей с использованием OpenXML и строки с разделителями - PullRequest
1 голос
/ 29 сентября 2010

У меня есть несколько имен сотрудников, которые нужно вставить в таблицу.

Должен ли я представлять мои данные таким образом и использовать OpenXML для вставки в базу данных: -

<Employees>
<Employee>
Emp1
</Employee>
<Employee>
Emp2
</Employee>
<Employee>
Emp2
</Employee>
</Employees>

OR

Я должен представлять Employee как Emp1,Emp2,Emp3, разбивать строку, добавлять в переменную таблицы и затем вставлять в таблицу базы данных.

Есть ли разница в производительности между этими двумя подходами. Обратите внимание, что это очень простая структура без вложенности сотрудников в XML и без более чем одного разделителя в строке. Этот XML также не будет использоваться в качестве схемы или чего-либо еще. Будет ли OpenXML излишним? Кто-нибудь может дать какое-то руководство по этому вопросу?

Ответы [ 3 ]

2 голосов
/ 29 сентября 2010

Используя поддержку SQL Server XQuery, вы можете легко разбить XML на биты:

INSERT INTO dbo.Employees(EmployeeName)
   SELECT 
      Data.Emp.value('(.)[1]', 'varchar(100)')
   FROM
      @Input.nodes('/Employees/Employee') AS Data(Emp)

Этого нельзя сказать о файлах CSV - поэтому я бы проголосовал за подход XML.

1 голос
/ 30 мая 2011

Самые большие проблемы с использованием табличных параметров:

1) Вы не можете изменить пользовательский тип таблицы.Вам нужно сбросить и воссоздать.2) Вы не можете удалить пользовательский тип таблицы, если на него ссылается другой объект, то есть сохраненный процесс или функция

Учитывая это, если ваш UDTT используется в нескольких хранимых процессах или функциях, вам нужно удалить их всеудалите UDTT, воссоздайте UDTT, а затем воссоздайте все свои SP.

0 голосов
/ 29 сентября 2010

Ну, в зависимости от того, какую версию SQL вы используете, существует третий вариант, который очень прост.Если вы используете SQL 2008, тогда вы можете создать пользовательский тип таблицы.

CREATE TYPE [dbo].[IntegerList] AS TABLE(
    [n] [VARCHAR(100)] NOT NULL,
    PRIMARY KEY CLUSTERED 
(
    [n] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO

Я использовал это с целыми числами, но я не понимаю, почему вы не могли просто изменить тип на varchar.Затем вы используете его следующим образом:

CREATE PROCEDURE [dbo].[CheckIds]
    @Ids    IntegerList READONLY
AS
BEGIN
    SELECT *
    FROM [dbo].[Table]  
    WHERE [Id] IN (SELECT n FROM @Ids)
END

Затем в вашем .net-коде вы устанавливаете его так:

int[] Ids = <You id array>
var IdList = new List<SqlDataRecord>();
SqlMetaData[] tvp_definition = { new SqlMetaData("n", SqlDbType.Int) };

foreach (int Id in Ids)
{
    var rec = new SqlDataRecord(tvp_definition);
    rec.SetInt32(0, Id);
    IdList.Add(rec);
}

Затем передаете его как параметр, как обычно, для хранимого вызова procза исключением некоторых небольших изменений:

sqlCommand.Parameters.Add(new SqlParameter { ParameterName = "@Ids", SqlDbType = SqlDbType.Structured, TypeName = "IntegerList", Value = IdList });

Может показаться, что это много, но на самом деле это не так.Это действительно чистый и без лишнего кода парсинга xml или строк.

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

...