簡體   English   中英

遍歷動態數據集並插入存儲過程

[英]Loop through dynamic DataSet and insert Stored Procedure

我在C#中有一個DataTable,需要將其插入表中。 DataTable是完全動態的(未預定義列)。 我使用C#代碼逐行插入了此DataTable,但是由於效率低下,我將DataTable批量發送到SQL存儲過程中。 我需要存儲過程來循環遍歷批量,一行一行插入並返回無效數據集。

C#代碼:

SqlConnection sqlConnection = getDBConnection();
SqlCommand command = sqlConnection.CreateCommand();

command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "[dbo].[saveDataIntoTable]";

SqlParameter parameter = new SqlParameter();

//The parameter for the SP must be of SqlDbType.Structured
parameter.ParameterName = "@Sample";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = dataTable;

command.Parameters.Add(parameter);

        foreach (DataRow row in dataTable.Rows)
        {
            System.Diagnostics.Debug.WriteLine(row.ItemArray);
            if (row.ItemArray[0] == null)
            {
                dataTable.Rows.Remove(row);
            }
        }

SqlDataReader dr = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);

//handling the dt DataTable here

存儲過程:

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[saveDataIntoTable]
(
    -- which accepts one table value parameter. It should be noted that   the parameter is readonly
    @Sample As [dbo].[SampleUserData] Readonly
)
AS
BEGIN

BEGIN TRY

    Insert  Into    USER(USER_ID,EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
        CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE)
        Select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
        CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE From @Sample

END TRY
BEGIN CATCH
    Select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
        CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE From @Sample 
END CATCH
END

我為存儲過程使用了用戶定義的表類型:

-- Create a table data type
CREATE TYPE [dbo].[SampleUserData] As Table
(
        --This type has structure similar to the DB table           
        USER_ID Nvarchar(20) ,
        EMAIL Nvarchar(50),
        PASSWORD Nvarchar(100),

        PASSWORD_HINT Nvarchar(20),
        PWD_CHANGED_DATE date,
        CREATED_BY Nvarchar(20),

        CREATED_DATE date,
        UPDATED_BY Nvarchar(20),
        UPDATED_DATE date,
        STATUS Nvarchar(20),
        VERSION Int,
        VALIDATE Nvarchar(10)

);

現在,我的存儲過程一次插入了全部數據。 發生異常時,它將返回整個DataSet(我不知道如何分隔行)。

PS:如果在上述情況下還有其他更簡便的方法,請告訴我。

謝謝。

為什么不使用where子句來驗證數據

-- insert valid data
insert into [USER] (USER_ID,EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
                  CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE)
select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
       CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from @Sample
where USER_ID is not null

-- select invalid data
select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
       CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from @Sample
where USER_ID is null

更詳細的驗證檢查的示例

select USER_ID, EMAIL,PASSWORD,PASSWORD_HINT,PWD_CHANGED_DATE,
       CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,STATUS,VERSION,VALIDATE
from @Sample S
where USER_ID is not null
and EMAIL is not null
and PASSWORD is not null -- etc
-- check record is not duplicate
and not exists (select 1 from [USER] U where U.USER_ID = S.USER_ID)
and isnumeric(USER_ID)

這將與您的存儲過程一次執行同一行:這是為SQL Server 2005編寫的

BEGIN
--I'm only using your first three columns in this example
DECLARE @USER_ID as Nvarchar(20);
DECLARE @Email as Nvarchar(20);
DECLARE @Password as Nvarchar(20);
DECLARE @SampleCursor as CURSOR;

SET @SampleCursor = CURSOR FOR
SELECT USER_ID, EMAIL, PASSWORD
 FROM  @Sample;
OPEN @SampleCursor;
--Can't insert directly into table from table variable so save as scalar variable first
FETCH NEXT FROM @SampleCursor INTO @USER_ID, @Email, @Password;

WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM @SampleCursor INTO @USER_ID, @Email, @Password;
BEGIN TRY
--then insert scalar variables into table
INSERT INTO USER (USER_ID, Email, Password) VALUES( @USER_ID, @Email, @Password)
END TRY
BEGIN CATCH
SELECT  @USER_ID, @Email, @Password
END CATCH
END

CLOSE @SampleCursor;
DEALLOCATE @SampleCursor;
END

這可能有效。 只需使用TOP(1)一次將源表插入一行。 以下解決方案臨時創建了一個表,因此不會刪除您的源表。

--create copy of source table
SELECT * INTO TempTbl FROM Source_Table
--loop through temp table
WHILE EXISTS (SELECT * FROM TempTbl)
BEGIN
--insert first line of temp table into destination table
BEGIN TRY 
INSERT INTO [USER] SELECT TOP (1) * FROM TempTbl
END TRY
BEGIN CATCH
SELECT TOP(1) FROM TempTbl
END CATCH
--remove inserted line from temp table
DELETE TOP (1) FROM TempTbl
END
DROP TABLE TempTbl

更新。

這對我有用:

CREATE PROCEDURE SOProc 
    -- Add the parameters for the stored procedure here
    @Source_Table_Name sysname = '' 
AS
BEGIN
EXEC(
'SELECT * INTO TempTbl FROM ' +  @Source_Table_Name)
WHILE EXISTS (SELECT * FROM TempTbl)
BEGIN
BEGIN TRY 
INSERT INTO User_Table SELECT TOP (1) * FROM TempTbl
END TRY
BEGIN CATCH
SELECT TOP(1) * FROM TempTbl
END CATCH
DELETE TOP (1) FROM TempTbl
END
DROP TABLE TempTbl
END
GO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM