2015-10-20 129 views
1

我在這裏是新手,目前遇到麻煩,我的方案是我想從Excel插入和更新數據到SQL Server表中。操作數類型衝突:nvarchar與用戶定義的表類型不兼容

對於插入部分它完美的作品,但是當涉及到更新時,我不知道該怎麼做。我搜索了很少的方法,我發現這對我來說最適合使用存儲過程。

這是我現在使用的代碼。當我嘗試它給了我這個錯誤:

Operand type clash: nvarchar is incompatible with user-defined table type

--- Stored procedure --- 
CREATE PROCEDURE [dbo].[chkUpdate] 
    @Operator IC_CHK READONLY 
AS 
BEGIN 
    set nocount on; 

    MERGE INTO tb_Operator c1 
    USING @Operator c2 ON c1.IC = c2.IC 

    WHEN MATCHED THEN 
     UPDATE SET 
      c1.Name = c2.Name, 
      --c1.IC = c2.IC, 
      c1.Email = c2.Email, 
      c1.Status = c2.Status, 
      c1.Datetime = c2.Datetime 

    WHEN NOT MATCHED THEN 
     INSERT VALUES(c2.Name, c2.IC, c2.Email, c2.[Status], c2.[Datetime]); 
end 

--- User-defined table type --- 
CREATE TYPE [dbo].[IC_CHK] as table 
(
    [Id] [int] NULL, 
    [Name] [nvarchar](50) NULL, 
    [IC] [bigint] NULL, 
    [Email] [nvarchar](MAX) NULL, 
    [Status] [nvarchar](50) NULL, 
    [Datetime] [datetime] NULL 
) 

VS 2010代碼:

protected void btnImport_Click1(object sender, EventArgs e) 
{ 
    int i = 0; 

    try 
    { 
     string path = string.Concat(Server.MapPath("~/Excel/" + UploadExcel.FileName)); 
     UploadExcel.SaveAs(path); 

     String strCon = string.Format("Provider=Microsoft.Ace.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;",path); 
     OleDbDataAdapter myda = new OleDbDataAdapter("SELECT * FROM [sheet1$]", strCon); 

     DataTable myds = new DataTable(); 
     myda.Fill(myds); 

     for (i = 0; i <= myds.Rows.Count - 1; i++) 
     { 
      String constr = ConfigurationManager.ConnectionStrings["conn"].ConnectionString; 

      using (SqlConnection con = new SqlConnection(constr)) 
      using (SqlCommand cmd = new SqlCommand("chkUpdate")) 
      { 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Connection = con; 

       cmd.Parameters.AddWithValue("@Operator", path); 

       con.Open(); 
       cmd.ExecuteNonQuery(); 
       con.Close(); 
      } 
     } 

     MsgBox1.alert("Import success"); 
     View.Visible = true; 

     vBinds(); 
    } 
    catch (Exception ex) 
    { 
     MsgBox1.alert(ex.Message); 
    } 
} 

做檢查,我和我欣賞它。謝謝

P/S:我再次確認我的用戶定義表類型與我的表具有相同的數據類型。

+0

你應該檢查(HTTP [我們可以停止使用AddWithValue()了嗎?]://blogs.msmvps .com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already /)並停止使用'.AddWithValue()' - 它可能會導致意想不到的結果... –

+0

加載你的數據到一個'DataTable'中,如果你想傳遞一個表值參數,這是正確的。然後你忽略它,而是將字符串* path *傳遞到數據的起始位置,而不是將DateTable對象傳入。 –

+0

@Damien_The_Unbeliever謝謝我剛剛注意到這一點。 – TheButterfly

回答

0

在您的MERGE聲明中的INSERT中,我會建議明確定義您要插入的列。最有可能的是,這是錯誤的原因 - 你插入你的列 - 但你沒有指定哪些目標列應插入。

既然你不指定,你必須爲表中的每一列提供值,在定義它們的確切順序 - 是真的如此?例如。你在表格中插入什麼ID列?

假設您的實際數據庫表中的列IDIDENTITY列,我會用(否則,你必須列出ID在列的列表中插入以及和的VALUES列表提供一個值值):

WHEN NOT MATCHED THEN 
    INSERT(Name, IC, Email, [Status], [DateTime]) 
    VALUES(c2.Name, c2.IC, c2.Email, c2.[Status], c2.[Datetime]); 

,我會還建議不使用T-SQL保留關鍵字statusdatetime爲您列名 - 你只是要求這樣做的麻煩。使用更具表現的名字 - 這確實涉及到你的業務領域 - 不僅datetime .....

+0

感謝您的建議,並修復了錯誤。我會爲剛剛發現的錯誤而自行處理;) – TheButterfly

相關問題