Je crois que vous cherchez un paramètre de table Vous pouvez le remplir à partir d'un ensemble de données et, en supposant que vous ne fassiez rien de stupide lorsque vous le transmettez à SQL Server, il sera traité comme une opération atomique ; tout ou rien.
IF EXISTS
(
SELECT
*
FROM
sys.types T
WHERE
T.name = 'CONTRIVED_EXAMPLE'
)
BEGIN
PRINT 'Dropping type dbo.CONTRIVED_EXAMPLE'
DROP TYPE dbo.CONTRIVED_EXAMPLE
END
PRINT 'Creating type dbo.CONTRIVED_EXAMPLE'
GO
-----------------------------------------------------------------------------
-- Type: dbo.CONTRIVED_EXAMPLE
-- Author: Bill Fellows
-- Date: 2010-06-07
--
-- This is a user-defined table type demonstrating the syntax
-- for a table valued parameter
--
-- See also:
--
-- Modified:
--
-----------------------------------------------------------------------------
CREATE TYPE
dbo.CONTRIVED_EXAMPLE AS TABLE
(
twitter_handle varchar(15) NOT NULL
, have_met bit NOT NULL
)
GO
IF EXISTS
(
SELECT
*
FROM
sys.tables T
WHERE
T.name = 'CONTRIVED_EXAMPLE_TABLE'
)
BEGIN
PRINT 'Dropping type dbo.CONTRIVED_EXAMPLE_TABLE'
DROP TABLE dbo.CONTRIVED_EXAMPLE_TABLE
END
PRINT 'Creating table dbo.CONTRIVED_EXAMPLE_TABLE'
GO
-----------------------------------------------------------------------------
-- Type: dbo.CONTRIVED_EXAMPLE_TABLE
-- Author: Bill Fellows
-- Date: 2010-06-07
--
-- This is a boring table demonstrating the syntax
-- for a table valued parameter
--
-- See also:
--
-- Modified:
--
-----------------------------------------------------------------------------
CREATE TABLE
dbo.CONTRIVED_EXAMPLE_TABLE
(
row_id int identity(1,10) NOT NULL PRIMARY KEY
, twitter_handle varchar(15) NOT NULL
, have_met bit NOT NULL
)
GO
IF EXISTS
(
SELECT
SO.*
FROM
dbo.sysobjects SO
WHERE
SO.id = OBJECT_ID('dbo.EchoBack')
AND OBJECTPROPERTY(SO.id, 'IsProcedure') = 1
)
BEGIN
PRINT 'Dropping stored procedure dbo.EchoBack'
DROP PROCEDURE dbo.EchoBack
END
GO
PRINT 'Creating stored procedure dbo.EchoBack'
GO
-----------------------------------------------------------------------------
-- Function: dbo.EchoBack
-- Author: Bill Fellows
-- Date: 2010-06-07
--
-- This procedure handles merging
--
-- Recordsets:
-- The contents of our table valued parameter will be echoed back to the
-- caller.
--
-- Side-effects:
-- None
--
-- See also:
-- your mom
--
-- Modified:
--
-----------------------------------------------------------------------------
CREATE PROCEDURE dbo.EchoBack
(
@tvp dbo.CONTRIVED_EXAMPLE READONLY
)
AS
BEGIN
SET NOCOUNT ON
SELECT
T.*
FROM
@tvp T
END
GO
PRINT 'Granting rights for dbo.EchoBack'
GRANT EXECUTE ON dbo.EchoBack TO public
GO
DECLARE @p1 dbo.CONTRIVED_EXAMPLE
INSERT INTO @p1 values('billinkc', 1)
INSERT INTO @p1 values('peschkaj', 1)
INSERT INTO @p1 values('mikeSQL', 1)
INSERT INTO @p1 values('SQLChicken', 0)
SELECT * FROM @p1
EXECUTE dbo.EchoBack @p1
GO
IF EXISTS
(
SELECT
SO.*
FROM
dbo.sysobjects SO
WHERE
SO.id = OBJECT_ID('dbo.TwitterAdd')
AND OBJECTPROPERTY(SO.id, 'IsProcedure') = 1
)
BEGIN
PRINT 'Dropping stored procedure dbo.TwitterAdd'
DROP PROCEDURE dbo.TwitterAdd
END
GO
PRINT 'Creating stored procedure dbo.TwitterAdd'
GO
-----------------------------------------------------------------------------
-- Function: dbo.TwitterAdd
-- Author: Bill Fellows
-- Date: 2010-06-07
--
-- This procedure handles merging
--
-- Recordsets:
-- Business rule violations (optional)
--
-- Side-effects:
-- 0-N rows written to twitter table
--
-- See also:
-- CONTRIVED_EXAMPLE (your mom)
--
-- Modified:
--
-----------------------------------------------------------------------------
CREATE PROCEDURE dbo.TwitterAdd
(
@tvp dbo.CONTRIVED_EXAMPLE READONLY
)
AS
BEGIN
SET NOCOUNT ON
MERGE
dbo.CONTRIVED_EXAMPLE_TABLE DESTINATION
USING
(SELECT twitter_handle, have_met FROM @tvp T) AS SOURCE (twitter_handle, have_met)
ON (SOURCE.twitter_handle = DESTINATION.twitter_handle)
-- Never forget I met someone
WHEN MATCHED AND DESTINATION.have_met = 0
THEN UPDATE SET DESTINATION.have_met = SOURCE.have_met
WHEN NOT MATCHED
THEN INSERT(twitter_handle, have_met) VALUES (SOURCE.twitter_handle, SOURCE.have_met)
-- merge statements must be terminated by a semi-colon
-- and don't you forget it!
;
END
GO
PRINT 'Granting rights for dbo.TwitterAdd'
GRANT EXECUTE ON dbo.TwitterAdd TO public
GO
À ce stade, vous pouvez voir comment fonctionne le TVP. La seule étape restante consiste à le lier à votre code .NET. Quelque chose comme
/// <summary>
/// This method demonstrates the ease of passing a dataset in
/// as a TVP
/// </summary>
public static void TSQLTuesday007()
{
string connectionString = @"Data Source=localhost;Initial Catalog=master;Integrated Security=True";
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connectionString);
System.Data.DataTable dataTable = null;
// note that my data table does not have to be the same
// as my UDTT, nor do my columns have to have the same name
// Types-yes. Ordinal, probably so
dataTable = new System.Data.DataTable("Sample");
dataTable.Columns.Add("tweep", System.Type.GetType("System.String"));
dataTable.Columns.Add("have_met", System.Type.GetType("System.Boolean"));
// add rows to my data table but really, this could be any source
dataTable.Rows.Add(new object[] { "billinkc", true });
dataTable.Rows.Add(new object[] { "BrentO", true });
dataTable.Rows.Add(new object[] { "buckwoody", false });
// Hooray for #sqlsat35 and meeting Jen & Sean
dataTable.Rows.Add(new object[] { "MidnightDBA", true });
System.Data.SqlClient.SqlConnection connection = null;
System.Data.DataSet results = null;
System.Data.SqlClient.SqlCommand command = null;
System.Data.SqlClient.SqlDataReader dataReader = null;
connection = new System.Data.SqlClient.SqlConnection(connectionString);
try
{
connection.Open();
command = new System.Data.SqlClient.SqlCommand("TwitterAdd");
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Connection = connection;
// Assigning a table valued parameter looks much like any other parameter
System.Data.SqlClient.SqlParameter tvp = command.Parameters.AddWithValue("@tvp", dataTable);
// this is the only special sauce (not required but helpful)
tvp.SqlDbType = System.Data.SqlDbType.Structured;
tvp.TypeName = "dbo.CONTRIVED_EXAMPLE";
dataReader = command.ExecuteReader();
if (dataReader.HasRows)
{
results = new System.Data.DataSet();
results.Tables.Add();
results.Tables[0].Load(dataReader);
// PPrint(results);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}