[英]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.