SQL Server Express 2008を使用して簡単なデモGo言語データベースプログラムを作成した経験を共有したいと思います。以下の教訓は、2008以降のすべてのSQLServerバージョンに適用されると思います。
私のSQLServerExpressは、以前はdefault
でインストールされていました named
ではなくインスタンス 実例。また、Windows認証を使用するためにインストールされました。これらの設定は両方とも、私が行う他の開発作業で必要でした。私が行う他の作業では、ローカルデータベースエンジンとしてアプリケーションと同じPC上でSQLServerExpressを使用します。 GoアプリケーションでSQLServerでWindows認証を使用できることを期待していました。
ローカルのSQLServerとGoで使用するドライバーと小さなサンプルプログラムを探していたところ、この質問が私の検索で見つかりました。他の人が自分の過ちから始めて学ぶのを助けるために、少しの追加情報とサンプルプログラムを追加しようと思いました。また、この記事「GoLangとMSSQLデータベース:例」は、十分な間違いを犯した後、よく理解できたので役に立ちました。
私のテストプログラムの最終バージョンは次のとおりです。
package main
import (
"fmt"
"log"
"database/sql"
_ "github.com/denisenkom/go-mssqldb" // the underscore indicates the package is used
)
func main() {
fmt.Println("starting app")
// the user needs to be setup in SQL Server as an SQL Server user.
// see create login and the create user SQL commands as well as the
// SQL Server Management Studio documentation to turn on Hybrid Authentication
// which allows both Windows Authentication and SQL Server Authentication.
// also need to grant to the user the proper access permissions.
// also need to enable TCP protocol in SQL Server Configuration Manager.
//
// you could also use Windows Authentication if you specify the fully qualified
// user id which would specify the domain as well as the user id.
// for instance you could specify "user id=domain\\user;password=userpw;".
condb, errdb := sql.Open("mssql", "server=localhost;user id=gouser;password=g0us3r;")
if errdb != nil {
fmt.Println(" Error open db:", errdb.Error())
}
defer condb.Close()
errdb = condb.Ping()
if errdb != nil {
log.Fatal(errdb)
}
// drop the database if it is there so we can recreate it
// next we will recreate the database, put a table into it,
// and add a few rows.
_, errdb = condb.Exec("drop database mydbthing")
if errdb != nil {
fmt.Println(" Error Exec db: drop db - ", errdb.Error())
}
_, errdb = condb.Exec("create database mydbthing")
if errdb != nil {
fmt.Println(" Error Exec db: create db - ", errdb.Error())
}
_, errdb = condb.Exec("use mydbthing")
if errdb != nil {
fmt.Println(" Error Exec db: using db - ", errdb.Error())
}
_, errdb = condb.Exec("create table junky (one int, two int)")
if errdb != nil {
fmt.Println(" Error Exec db: create table - ", errdb.Error())
}
_, errdb = condb.Exec("insert into junky (one, two) values (101, 201)")
if errdb != nil {
fmt.Println(" Error Exec db: insert table 1 - ", errdb.Error())
}
_, errdb = condb.Exec("insert into junky (one, two) values (102, 202)")
if errdb != nil {
fmt.Println(" Error Exec db: insert table 2 - ", errdb.Error())
}
_, errdb = condb.Exec("insert into junky (one, two) values (103, 203)")
if errdb != nil {
fmt.Println(" Error Exec db: insert table 3 - ", errdb.Error())
}
// Now that we have our database lets read some records and print them.
var (
one int
two int
)
// documentation about a simple query and results loop is at URL
// http://go-database-sql.org/retrieving.html
// we use Query() and not Exec() as we expect zero or more rows to
// be returned. only use Query() if rows may be returned.
fmt.Println (" Query our table for the three rows we inserted.")
rows, errdb := condb.Query ("select one, two from junky")
defer rows.Close()
for rows.Next() {
err:= rows.Scan (&one, &two)
if err != nil {
fmt.Println(" Error Query db: select - ", err.Error())
} else {
fmt.Printf(" - one %d and two %d\n", one, two)
}
}
rows.Close()
errdb = rows.Err()
if errdb != nil {
fmt.Println(" Error Query db: processing rows - ", errdb.Error())
}
fmt.Println("ending app")
}
SQL Serverの設定に必要な変更を加えた後、上記のアプリケーションを初めて実行すると、次の出力が生成されます。プログラムを初めて実行したときにはデータベースが存在しないため、エラーメッセージが出力されます。ただし、それ以降の実行時にはデータベースが存在し、データベースがドロップされたときのエラーメッセージは出力されません。
starting app
Error Exec db: drop db - mssql: Cannot drop the database 'mydbthing', because it does not exist or you do not have permission.
Query our table for the three rows we inserted.
- one 101 and two 201
- one 102 and two 202
- one 103 and two 203
ending app
SQLServerドライバーパッケージのインストール
私が最初にやらなければならなかったのは、SQLServerで動作するデータベースドライバーパッケージを見つけることでした。いくつかのstackoverflowの投稿は、github.com/denisenkom/go-mssqldb
を推奨しています それが使用されたものです。
github.com/denisenkom/go-mssqldb
を使用するには パッケージ最初にgo get github.com/denisenkom/go-mssqldb
を使用してgithubリポジトリから取得する必要がありました Git Shell
を実行して作成されたコマンドシェルウィンドウから 。
Git Shell
Gitのインストールの一部としてインストールされるgithubシェルです。 go get
を実行する必要があることがわかりました Git Shell
のコマンド go
のために git
を検索するコマンド アプリケーションを作成し、githubリポジトリにアクセスします。 go get
を実行しようとしたとき 通常のコマンドシェルからのコマンドgit
を示すエラーメッセージが表示されました コマンドが見つかりませんでした。
go-mssqldb
をインストールした後 パッケージサンプルアプリケーションを実行でき、Open()
からランタイムエラーが発生し続けました 。私のアプリケーションからの出力は次のとおりです。
starting app
Error Exec db: create db - Unable to open tcp connection with host 'localhost:1433': dial tcp 127.0.0.1:1433: connectex: No connection could be made because the target machine actively refused it.
ending app
SQLServerのTCP接続を有効にする
いくつか検索した後、いくつかの異なるサイトを見つけました。これらはすべて、エラーが私のSQLServerインスタンスがTCP/IP用に構成されていないことを意味していることを示していました。さまざまな投稿により、Sql Server Configuration Manager
を使用する必要があることが示されました TCP/IPを有効にします。
私が発見したのは、TCP/IPを有効にする必要がある場所が実際には2つあるということです。 1つはClient Protocols
でした そしてそれは確かにすでに有効にされていました。ただし、もう1つはProtocols for MSSQLSERVER
でした。 その中で、1つのTCP/IPが無効になりました。そこで、Protocols for MSSQLSERVER
でTCP/IPを有効にしました。 次に、コントロールパネルの管理ツールのサービスユーティリティを使用してSQLServerサービスを再起動します。
ただし、sql.Open()
を使用した後も、どのような種類のクエリでも問題が発生していました。 。次のバリエーションのアプリケーション出力が表示されていました。エラーメッセージは同じですが、関数呼び出しでエラーが発生した場合、実行ごとにエラーが変わる可能性があります。 sql.Open()
で指定された接続文字列を変更してみました 異なるエラーメッセージ以外の結果はありません。
starting app
Error Exec db: create db - driver: bad connection
Error Exec db: create table - driver: bad connection
ending app
さらに調べてみると、このメモがgithubリポジトリにあります:
既知の問題
SSL暗号化が無効になっていない場合、SQLServer2008および2008R2エンジンはログインレコードを処理できません。 SQL Server 2008 R2の問題を修正するには、SQL Server 2008 R2 Service Pack 2をインストールします。SQLServer2008の問題を修正するには、SQL Server2008SP3用のMicrosoftSQLServer 2008 ServicePack3とCumulativeupdateパッケージ3をインストールします。詳細:http://support.microsoft.com/kb/2653857
そこで、実際にインストールしたことのないアップデートをダウンロードしました。ダウンロードを待っている間、私はさらに調べて、実際のSQLServer実行可能ファイルとLog
を含むフォルダーを見つけました。 一連のファイルを含むフォルダERRORLOG
、ERRORLOG.1
、など。
SQLServerログはSQLServerユーザーが必要であることを示しています
ERRORLOG
を見る ファイル次のパズルのピースを提供する次のログを含むSQLServerのエラーログを見つけました:
2016-08-15 22:56:22.41 Server SQL Server is now ready for client connections. This is an informational message; no user action is required.
2016-08-15 23:55:47.51 Logon Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.51 Logon Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]
2016-08-15 23:55:47.61 Logon Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.61 Logon Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: ::1]
2016-08-15 23:55:47.62 Logon Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.62 Logon Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]
次に、Go SQL ServerドライバーがWindows認証を使用しておらず、代わりにSQLServer認証を使用していることに気付きました。空のuser id=
を指定してWindows認証を使用しようとしました しかし、それはうまくいかなかったようです。したがって、sqlcmd
を使用します ユーティリティ、SQLServerユーザーを作成しました。
1> create login gouser with password='g0us3r';
2> go
1> create user gouser for login gouser;
2> go
次に、Microsoft SQL ServerManagementStudioをダウンロードしてインストールしました。これは、SQLServer構成マネージャーとは異なるユーティリティです。これを使用して、2つのことを行いました。(1)SQL Server認証とWindows認証をオンにし、(2)新しいSQLServerユーザーgouser
に必要なアクセス許可を提供しました。 。このユーティリティは、SQLServerとそのさまざまなデータベースを参照するための優れたユーザーインターフェイスも提供しました。
作成するSQLユーザーに、SQLServerへの接続とデータベースの作成に使用できる十分な権限があることを確認してください。
Windows認証を使用する際の考慮事項
さらに調査した結果、実際にWindows認証を使用できることがわかりましたが、完全に修飾されたユーザーIDとそのパスワードを提供する必要があります。ドメイン名が「AD」のActiveDirectoryを使用している環境の場合、完全修飾ユーザーIDは「AD \ userid」になり、ローカルホストの場合は「\userid」になります。現在ログインしているユーザーの資格情報を自動的に使用できるようにすることについては、まだ調査中です。
さらに調査し、Goドライバー開発者からの支援を見つけた後、sql.Open()
があれば、現在のWindows認証が可能になるはずです。 「userid=;password=;」を意味するユーザー情報は含まれません。指定しないでください。
ただし、現在のユーザーに対するこの形式の自動Windows認証は、SQL Serverインスタンスが有効なサービスプリンシパル名(SPN)でKerberosを使用している場合にのみ許可されます。 SQL Serverのインスタンスで再起動を実行し、ERRORLOGファイルに次のログが表示される場合、SQLServerはKerberosで初期化できませんでした。
2016-08-23 18:32:16.77サーバーSQL Serverネットワークインターフェイスライブラリは、SQL Serverサービスのサービスプリンシパル名(SPN)を登録できませんでした。エラー:0x54b、状態:3。SPNの登録に失敗すると、統合認証がKerberosではなくNTLMにフォールバックする可能性があります。これは情報メッセージです。認証ポリシーでKerberos認証が必要な場合にのみ、追加のアクションが必要です。
setspn
を使用していくつかの追加情報を提供するSQLServer2005のインスタンスへのリモート接続を作成するときに、Kerberos認証を使用していることを確認する方法も参照してください。 問題を修正するコマンド。
SQLネットワークインターフェイスライブラリがSPNを登録できませんでした。
も参照してください。信頼できるWindows認証について (@xptによる@Richardからの要求に従って更新)
Windows認証は、ユーザーIDとパスワードを指定せずに、Windowsクレデンシャルを使用してSQLServerにログインしています。これは、sqlcmd
の信頼できる接続と呼ばれます またはODBC
;または、go-mssqldb
のシングルサインオンと呼ばれます ドライバーパッケージに移動します。
go-mssqldb
から githubでのreadme、
「ユーザーID」-SQLServer認証ユーザーIDまたはWindowsAuthenticationユーザーIDをDOMAIN\User形式で入力します。 Windowsでは、ユーザーIDが空であるか欠落している場合、シングルサインオンが使用されます。
そこで、SQL Server 2008 R2で次の2つの方法を試しましたが、どちらも正常に機能しています。
condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=DONTCARE;")
condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=;")
正しいホスト名を使用することが重要であるため、server =localhostの使用は失敗することに注意してください。その名前から、ドライバーはSQL Server kerberosサービスプリンシパル名(SPN)を構築し、その名前はSQLServerの名前と一致する必要があります。テストで適切なサービスプリンシパル名(SPN)を使用したので、機能します。