none
關於 VB2005 Express 連接 SQL資料庫 的2個問題(輸入中文變? 及 IDENTITY_INSERT) RRS feed

  • 問題

  • 小弟正在撰寫一個管理個人在不同的網站所註冊的'使用者名稱'及'密碼'的工具, 現在遇到了 2 個問題:


      1.於表單控制項的 中文文字 無法確實傳送到 資料庫檔案內。
         例如:
         輸入 MSN台灣首頁 存到資料庫會變成 MSN????

    2.無法使用 INSERT INTO 新增記錄。會顯示以下錯誤訊息:
        
    An explicit value for the identity column in table 'Website' can
         only be specified when a column list is used and IDENTITY_INSERT
         is ON.

     

    >> 附註:

     > 小弟所使用的版本:
           Microsoft Visual Basic 2005 Express Edition(英文版)
           SQL Server 2005 Express(中文版)
       > 小弟設計此程式的元件:
        1. frm_Main        (Form, 主表單, '顯示記錄'及'連結網址')
        2. frmWebsiteInfo  (Form, 進行'新增記錄'及'修改記錄'的表單)
        3. myIdentity.mdf  (SQL Database, 由Data Source視窗產生)

     

     

          (主表單 frm_Main 的內容, 及表單示意)
       1. frm_Main
             lstWebsite    (ListBox)
             txtLinkURL    (TextBox)
             btnConnection (Button)
             btnNew        (Button)
             btnEdit       (Button)
             btnDelete     (Button)
             btnExit       (Button)
             cmbCatalog    (ComboBox)

     

           ------------------------------------------------------
          | frm_Main                                             |
          |------------------------------------------------------|
          | [btnNew]  [btnEdit]  [btnDelete]          [btnExit]  |
          |                                                      |
          | (TextBox: txtLinkURL)               [btnConnection]  |
          |                                                      |
          | (ListBox: lstWebsite)                                |
          |                                                      |
          |                                                      |
          |                                                      |
          |                                                      |
          | (ComboBox: cmbCatalog)                               |
           ------------------------------------------------------

           

           圖 frm_Main

     

     

     

          (表單 frmWebsiteInfo 的內容, 及表單示意)
       2. frmWebsiteInfo
             btnSave            (Button)
             btnExit            (Button)
             btnChangeCatalog   (Button)
             txtNumberOrder     (TextBox)
             txtWebsiteName     (TextBox)
             txtWebsiteURL      (TextBox)
             txtWebsitePoscript (TextBox)
             txtCatalog         (TextBox)
             cmnuCatalog        (ContextMenuStrip)

           ------------------------------------------------------
          | frmWebsiteInfo                                       |
          |------------------------------------------------------|
          |                                     [Save]   [Exit]  |
          | (TextBox: txtNumberOrder)                            |
          | (TextBox: txtWebsiteName)                            |
          | (TextBox: txtWebsiteURL)                             |
          | (TextBox: txtWebsitePoscript)                        |
          | (TextBox: txtCatalog)            [btnChangeCatalog]  |
          |                                                      |
           ------------------------------------------------------

           

            圖 frmWebsiteInfo     

     

     

     

       3. (myIdentity.mdf 的內容)
          Tables
             Website
                 WebsiteID   (bigint)
                 WebsiteName (ntext)
                 LinkURL     (ntext)
                 Comment     (ntext)
                 Catalog     (nchar10)
             WebsiteCatalog
                 Catalog     (nchar10)
             LoginInfo
                 WebsiteID   (bigint)
                 LoginID     (nvarchar50)
                 LoginPW     (nvarchar50)

     

     

    (frm_Main.vb的內容)

    Public Class frm_Main
        Dim conn As SqlClient.SqlConnection
        Dim myReader As SqlClient.SqlDataReader
        Dim myCmd As SqlClient.SqlCommand
        Dim ConnectionString As String = "Data Source=.\SQLEXPRESS;" _
                                       & "AttachDBFilename=|DataDirectory|myIdentity.mdf;" _
                                       & "Integrated Security=True;" _
                                       & "User Instance=True;"
       Public Sub New()

            ' This call is required by the Windows Form Designer.
            InitializeComponent()

            ' Add any initialization after the InitializeComponent() call.

            Default_ControlState(False)
       End Sub

     

     

     Private Sub frm_Main_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
            Me.txtLinkURL.Width = Me.Width - Me.btnConnection.Width - 20
       End Sub

     

     

     Private Sub frm_Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

          conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

     

          myCmd = New SqlClient.SqlCommand("SELECT Catalog FROM WebsiteCatalog", conn)
            myReader = myCmd.ExecuteReader()

     

          Me.cmbCatalog.Items.Add("Show all websites")
            While myReader.Read() = True
                Me.cmbCatalog.Items.Add("\ " & myReader(0).ToString())
            End While
            myReader.Close()

          conn.Close()
            conn.Dispose()
        End Sub

     

    Private Sub btnConnection_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnection.Click
            Process.Start(txtLinkURL.Text)
      End Sub

     

     

    Private Sub tlsNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click
            Dim myRecord As String()
            myRecord = lstWebsite.Text.Split(": ")

     

          conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

     

          myCmd = New SqlClient.SqlCommand("SELECT WebsiteID FROM Website;", conn)
            myReader = myCmd.ExecuteReader

          If myReader.Read() = True Then
                frmWebsitInfo.txtNumberOrder.Text = myReader(0).ToString()
            End If
            myReader.Close()

          conn.Close()
            conn.Dispose()

     

          frmWebsitInfo.Text = "New Website"
            frmWebsitInfo.ShowDialog()
      End Sub

     

     

     Private Sub btnEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEdit.Click
            If Not lstWebsite.Text = "" Then
                Dim myRecord As String()
                myRecord = lstWebsite.Text.Split(": ")

     

              conn = New SqlClient.SqlConnection(ConnectionString)
                conn.Open()

     

              myCmd = New SqlClient.SqlCommand("SELECT * FROM Website WHERE WebsiteID=" & myRecord(0) & ";", conn)
                myReader = myCmd.ExecuteReader

              If myReader.Read() = True Then
                    frmWebsitInfo.txtNumberOrder.Text = myReader(0).ToString()
                    frmWebsitInfo.txtWebsiteName.Text = myReader(1).ToString()
                    frmWebsitInfo.txtWebsiteURL.Text = myReader(2).ToString()
                    frmWebsitInfo.txtWebsitePostscript.Text = myReader(3).ToString()
                    frmWebsitInfo.txtCatalog.Text = myReader(4).ToString()

                  frmWebsitInfo.Text = "Edit - " & myReader(1).ToString()
                End If
                myReader.Close()

              conn.Close()
                conn.Dispose()

     

              frmWebsitInfo.ShowDialog()
            End If
        End Sub

     

     

      Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
            Command_Delete()
        End Sub

     

     

      Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
            End
        End
    Sub

     

     

     Private Sub cmbCatalog_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _

                                                                                cmbCatalog.SelectedIndexChanged

          conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

          myCmd = New SqlClient.SqlCommand("SELECT WebsiteID, WebsiteName FROM Website" & _

                                                                                                       showCatalog(cmbCatalog.Text), conn)
            myReader = myCmd.ExecuteReader()

          Me.lstWebsite.Items.Clear()
            While myReader.Read() = True
                Me.lstWebsite.Items.Add(myReader(0).ToString() & ": " & myReader(1).ToString())
            End While
            lstWebsite.Enabled = True
            myReader.Close()

          conn.Close()
            conn.Dispose()

     

          Me.txtLinkURL.Text = ""
            Default_ControlState(False)
        End Sub

     

     

     Private Sub lstWebsite_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _

                                                                             lstWebsite.SelectedIndexChanged
            If Not lstWebsite.Text = "" Then
                Dim myRecord As String()
                myRecord = lstWebsite.Text.Split(": ")

              conn = New SqlClient.SqlConnection(ConnectionString)
                conn.Open()

              myCmd = New SqlClient.SqlCommand("SELECT LinkURL FROM Website WHERE WebsiteID=" & _

                                                                                                CType(myRecord(0).ToString(), Integer) & ";", conn)
                myReader = myCmd.ExecuteReader

              If myReader.Read() = True Then Me.txtLinkURL.Text = (myReader(0).ToString())

     

              myReader.Close()

              conn.Close()
                conn.Dispose()

              Default_ControlState(True)
            End If

     End Sub

     


        ' TODO: Me.Controls(tlsConnection, btnEdit, btnDelete).Enalbled = (Boolean)PropertyEnabled
        '
        ' tlsConnection ::= ToolStrip
        ' btnEdit       ::= ToolStrip.Button
        ' vtnDelete     ::= ToolStrip.Button

      Private Sub Default_ControlState(ByVal PropertyEnabled As Boolean)
            Me.tlsConnection.Enabled = PropertyEnabled
            Me.btnEdit.Enabled = PropertyEnabled
            Me.btnDelete.Enabled = PropertyEnabled
        End Sub

     

     

      ' TODO: Database Command: Delete
        '
        ' Delete ::= Sub Command_Delete()   //delete a record from database.(Table:= Website, LoginInfo)

     Private Sub Command_Delete()
            If Not lstWebsite.Text = "" Then
                Dim myRecord As String()
                myRecord = lstWebsite.Text.Split(": ")

     

              conn = New SqlClient.SqlConnection(ConnectionString)
                conn.Open()

              myCmd = New SqlClient.SqlCommand("DELETE FROM LoginInfo WHERE WebsiteID='" & _

                              CType(myRecord(0).ToString(), Integer) & "'", conn)
                myCmd.ExecuteNonQuery()
                myCmd = New SqlClient.SqlCommand("DELETE FROM Website WHERE WebsiteID='" & _

                              CType(myRecord(0).ToString(), Integer) & "'", conn)
                myCmd.ExecuteNonQuery()

     

              conn.Close()
                conn.Dispose()
            End If
        End Sub

     


        ' TODO: Get catalog and return Sql segment code
        '
        ' Get catalog   ::= (string)getCatalog      << cmbCatalog.Text
        ' Set SQL code  ::= (string)setSqlCatalog   >> " WHERE Catalog='[setted catalog]'"

     Public Function showCatalog(ByVal getCatalog As String) As String
            Dim setSqlCatalog As String = ""

          If Mid(getCatalog, 1, 2) = "\ " Then
                setSqlCatalog = " WHERE Catalog='" & Mid(getCatalog, 3, 10) & "';"
            ElseIf getCatalog = "Show all websites" Then
                setSqlCatalog = ";"
            End If

            Return setSqlCatalog
        End Function
    End Class

     

     

    (frmWebsitInfo.vb 的內容)

    Public Class frmWebsitInfo
        Dim conn As SqlClient.SqlConnection
        Dim myReader As SqlClient.SqlDataReader
        Dim myCmd As SqlClient.SqlCommand
        Dim ConnectionString As String = "Data Source=.\SQLEXPRESS;" _
                                       & "AttachDBFilename=|DataDirectory|myIdentity.mdf;" _
                                       & "Integrated Security=True;" _
                                       & "User Instance=True;"

     

     

      Private Sub frmWebsitInfo_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

     

          myCmd = New SqlClient.SqlCommand("SELECT Catalog FROM WebsiteCatalog", conn)
            myReader = myCmd.ExecuteReader()

     

          Me.cmnuCatalog.Items.Clear()
            While myReader.Read() = True
                Me.cmnuCatalog.Items.Add(myReader(0).ToString())
            End While
            Me
    .cmnuCatalog.Items.Add("<New Catalog>")
            myReader.Close()

          conn.Close()
            conn.Dispose()
        End Sub

     

     

      Private Sub btnCatalog_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _

                                                               Handles btnChangeCatalog.MouseClick
            Me.cmnuCatalog.Show(Me.Location.X + btnChangeCatalog.Location.X + e.X + 4, _

                                               Me.Location.Y + btnChangeCatalog.Location.Y + e.Y + 30)
        End Sub

     

     

      Private Sub cmnuCatalog_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _

                                                                  Handles cmnuCatalog.MouseClick
            If Me.cmnuCatalog.GetItemAt(e.X, e.Y).Text = "<New Catalog>" Then
                MessageBox.Show("RaiseEvent ::= Add New Catalog"
            Else
                Me.txtCatalog.Text = Me.cmnuCatalog.GetItemAt(e.X, e.Y).Text
            End If
        End
    Sub

     

     

      Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
            If Me.Text = "New Website" Then
                Command_AddNew()
            Else
                Command_Update()
            End If
        End Sub

     

     

      Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
            Me.Dispose()
        End Sub

     

     


        ' Below following section is commands: Update, Insert
        '
        ' Update ::= Sub Command_Update()   //update a record to database
        ' Insert ::= Sub Command_AddNew()   //add a new record to database

      Private Sub Command_Update()
            conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

          Dim sqlUpdateString As String = "SET" _
                                          & " WebsiteName = '" & Me.txtWebsiteName.Text.Replace("'", "''") & "'," _
                                          & " LinkURL = '" & Me.txtWebsiteURL.Text.Replace("'", "''") & "'," _
                                          & " Comment = '" & Me.txtWebsitePostscript.Text.Replace("'", "''") & "'," _
                                          & " Catalog = '" & Me.btnChangeCatalog.Text.Replace("'", "''") & "'"
            myCmd = New SqlClient.SqlCommand("UPDATE Website " & sqlUpdateString & " WHERE WebsiteID='" & _

                          CType(txtNumberOrder.Text, Integer) & "'", conn)
            myCmd.ExecuteNonQuery()

          conn.Close()
            conn.Dispose()
         End Sub

     

     

        Private Sub Command_AddNew()
            conn = New SqlClient.SqlConnection(ConnectionString)
            conn.Open()

          myCmd = New SqlClient.SqlCommand("INSERT INTO Website VALUES(" & CType(txtNumberOrder.Text, Integer) & "," _
                                                                     & "'" & Me.txtWebsiteName.Text.Replace("'", "''") & "'" & "," _
                                                                     & "'" & Me.txtWebsiteURL.Text.Replace("'", "''") & "'" & "," _
                                                                     & "'" & Me.txtWebsitePostscript.Text.Replace("'", "''") & "'" & "," _
                                                                     & "'" & Me.txtCatalog.Text.Replace("'", "''") & "'" & ")" _
                                                                     , conn)

          myCmd.ExecuteNonQuery()    <<--------------------------------------------出現錯誤訊息的程式碼中斷點
            conn.Close()
            conn.Dispose()
        End Sub

    End Class

     

    2007年7月9日 下午 01:29

解答

  • 找到答案了!!!

     

     

     問題:

    1.於表單控制項的 中文文字 無法確實傳送到 資料庫檔案內。
         例如:
         輸入 MSN台灣首頁 存到資料庫會變成 MSN????

     

    引述 小朱 大大的回覆:

    你的資料表的欄位用的型別是 "varchar" 還是 "nvarchar" ? 用 nvarchar 才會正常寫入中文字  .

     

    解決方式:

    (1) 將SQL資料庫 內的欄位設為 nvarchar, ntext .....

    (2) 在 SqlCommand String 內的變數名稱前加上 N'

     

    參考資料:

    在 SQL Server 中處理 Unicode 字串常數時,必需為所有的 Unicode 字串加上前置詞 N

    >> http://support.microsoft.com/kb/239530/ZH-TW/

    Sql Server 2005 输入中文无法显示(簡體)

    >> http://omeweb.com/content.aspx?id=2270

     

    問題:

    2.無法使用 INSERT INTO 新增記錄。會顯示以下錯誤訊息:
        
    An explicit value for the identity column in table 'Website' can
         only be specified when a column list is used and IDENTITY_INSERT
         is ON.

    引述 小朱 大大的回覆:

    你所設定的自動編號欄位,不可以給定數值,那是由資料庫決定的 .

     

    解決方式 1:

    執行 T-SQL 的 INSERT 方法時不要插入設定自動編號的欄位。

    解決方式 2:

    於執行 T-SQL 的 INSERT 方法前先執行一段 SqlCommand 敘述字串

    "SET IDENTITY_INSERT database_name.schema_name.table  ON;",

    意思是開啟資料表內 指定欄位屬性為 Identity Specification=yes 的欄位設為 可以使用 INSERT 方法

    然後再執行你所要的 INSERT 敘述

     

    參考資料:

    SQL Server 2005 線上叢書: SET IDENTITY_INSERT (Transact-SQL)

    >> http://msdn2.microsoft.com/zh-tw/library/ms188059.aspx

    在 SQL Server 2005 中使用複寫功能執行資料表中的 INSERT 陳述式時,收到「必須為識別資料行指定外顯值」錯誤訊息

    >> http://support.microsoft.com/kb/908711/zh-tw
     

     

     

    2007年7月16日 上午 03:44

所有回覆

  •   1.於表單控制項的 中文文字 無法確實傳送到 資料庫檔案內。
         例如:
         輸入 MSN台灣首頁 存到資料庫會變成 MSN????

    2.無法使用 INSERT INTO 新增記錄。會顯示以下錯誤訊息:
        
    An explicit value for the identity column in table 'Website' can
         only be specified when a column list is used and IDENTITY_INSERT
         is ON.

     

    1. 你的資料表的欄位用的型別是 "varchar" 還是 "nvarchar" ? 用 nvarchar 才會正常寫入中文字 .

    2. 你所設定的自動編號欄位,不可以給定數值,那是由資料庫決定的 .

    2007年7月9日 下午 01:48
    版主
  •  

    謝謝小朱, 第二個問題解決了,

     

    不過我是先 Find 沒有用到的 ID 序號

    然後在 INSERT 之前加入

    myCmd = New SqlClient.SqlCommand("SET IDENTITY_INSERT dbo.Website ON", conn)

    myCmd.ExecuteNonQuery()

    這樣子比較費工, 要寫兩段 code , 你的方法較便利

     

    至於第一個問題...還沒有完全解決耶......

    輸入 MSN台灣首頁 存到資料庫還是會變成 MSN????

    不過若在資料庫直接輸入, 就沒有這種問題(就是以原汁原味的中文字去顯示)

     

    所以我在猜想, 是不是 VB 將值傳送到 資料庫 時的問題,

    也就是 文字編碼 (ANSI , Unicode, UTF8....)的問題

    因為若以 VB 的 MessageBox() 顯示 中文文字 是正常的

    我猜問題可能是:

       1. VB 所傳送到 資料庫的值 是以 ANSI(會讓中文字出現??的那種編碼) 的編碼傳送的

       2. 或者資料庫接收 VB 的值 是以 ANSI(會讓中文字出現??的那種編碼) 的編碼接收的

       3. 或者上面兩種情形一起出現

    這是我是自己的猜想....  但是我還是試不出來, 因為我不會設定編碼...

    2007年7月10日 上午 03:28
  • 1. 檢查你的資料表欄位使用的型別,必須要使用 Unicode 類型的才可以儲存非英文字。

    2. VB 預設是用 Unicode,所以你的猜想不太對。

    3. 檢查你的資料庫定序。

    2007年7月10日 上午 05:16
    版主
  • 小朱大大, 我投降了...

     

    我已經把資料庫的一部份改為 nvarchar 了

    結果還是一樣, 可能還有其他的問題吧

     

    我可不可以把檔案寄給你, 請你幫我看看...

    我真的弄不出來...被中文打敗了......

    2007年7月13日 下午 03:40
  • 找到答案了!!!

     

     

     問題:

    1.於表單控制項的 中文文字 無法確實傳送到 資料庫檔案內。
         例如:
         輸入 MSN台灣首頁 存到資料庫會變成 MSN????

     

    引述 小朱 大大的回覆:

    你的資料表的欄位用的型別是 "varchar" 還是 "nvarchar" ? 用 nvarchar 才會正常寫入中文字  .

     

    解決方式:

    (1) 將SQL資料庫 內的欄位設為 nvarchar, ntext .....

    (2) 在 SqlCommand String 內的變數名稱前加上 N'

     

    參考資料:

    在 SQL Server 中處理 Unicode 字串常數時,必需為所有的 Unicode 字串加上前置詞 N

    >> http://support.microsoft.com/kb/239530/ZH-TW/

    Sql Server 2005 输入中文无法显示(簡體)

    >> http://omeweb.com/content.aspx?id=2270

     

    問題:

    2.無法使用 INSERT INTO 新增記錄。會顯示以下錯誤訊息:
        
    An explicit value for the identity column in table 'Website' can
         only be specified when a column list is used and IDENTITY_INSERT
         is ON.

    引述 小朱 大大的回覆:

    你所設定的自動編號欄位,不可以給定數值,那是由資料庫決定的 .

     

    解決方式 1:

    執行 T-SQL 的 INSERT 方法時不要插入設定自動編號的欄位。

    解決方式 2:

    於執行 T-SQL 的 INSERT 方法前先執行一段 SqlCommand 敘述字串

    "SET IDENTITY_INSERT database_name.schema_name.table  ON;",

    意思是開啟資料表內 指定欄位屬性為 Identity Specification=yes 的欄位設為 可以使用 INSERT 方法

    然後再執行你所要的 INSERT 敘述

     

    參考資料:

    SQL Server 2005 線上叢書: SET IDENTITY_INSERT (Transact-SQL)

    >> http://msdn2.microsoft.com/zh-tw/library/ms188059.aspx

    在 SQL Server 2005 中使用複寫功能執行資料表中的 INSERT 陳述式時,收到「必須為識別資料行指定外顯值」錯誤訊息

    >> http://support.microsoft.com/kb/908711/zh-tw
     

     

     

    2007年7月16日 上午 03:44
  • 既然都已經放手讓資料庫去管 IDENTITY 的編號了,就不要自己插手比較好。

    除非真的必要。

    2007年7月16日 上午 04:23
    版主
  •  引述:

    既然都已經放手讓資料庫去管 IDENTITY 的編號了,就不要自己插手比較好。

    除非真的必要。

     

     

    嗯! 非常贊成!

    2007年7月16日 上午 10:51