C# : データベースを DataSet クラスで更新する / フィールドに値をセットして Update

更新の SQL を作成せずに、DataRow オブジェクトの中のフィールドに対して個別にデータをセットします。ここでは、 System.Data.SqlClient を使用していますが、OleDb や Odbc でも同じです。

▼ DataAdapter を使用した更新方法のサンプル
DataAdapter.Update(DataSet) Method
▼ 列にデータをセットする方法のサンプル
DataColumn Class
▼ 各オブジェクトの参照方法のサンプル
DataSet.Tables Property
▼ 接続からの全体像
DataSet Class
▼ DataSet 内の Table と言う名称について
複数のselect文をまとめて実行するには?
using System;
using System.Data;
using System.Data.SqlClient;

namespace DBUpdate1
{
	class Program
	{
		static void Main(string[] args)
		{
			DataSet dataSet = new DataSet();
			string connectionString;
			string queryString = "select * from 社員マスタ where 社員コード = '0001'";

			SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
			// 接続用のパラメータを追加
			builder.Add("Data Source", "layla");
			builder.Add("Initial Catalog", "lightbox");
			builder.Add("User ID", "sa");
			builder.Add("Password", "");

			// 接続文字列を取得
			connectionString = builder.ConnectionString;

			using (SqlConnection connection = new SqlConnection(connectionString))
			{
				// 接続
				connection.Open();
				SqlDataAdapter adapter = new SqlDataAdapter();
				// 参照用のマップを追加
				adapter.TableMappings.Add("Table", "社員マスタ");

				// SQL 作成
				SqlCommand command = new SqlCommand(queryString,connection);
				command.CommandType = CommandType.Text;
				adapter.SelectCommand = command;

				// 更新用のオブジェクトを準備
				SqlCommandBuilder commandBuilder = new SqlCommandBuilder(adapter);

				// データを取り出す
				adapter.Fill(dataSet);

				// テーブルを取得
				DataTable dataTable = dataSet.Tables["社員マスタ"];

				// 行と列の数( ここでは行は 1 )
				Console.WriteLine($"行数 : {dataTable.Rows.Count}");
				Console.WriteLine($"列数 : {dataTable.Columns.Count}");

				// 行
				DataRow row = dataTable.Rows[0];

				// 列の定義
				DataColumn column = dataTable.Columns["氏名"];
				Console.WriteLine($"氏名 : {column.DataType.ToString()}");
				column = dataTable.Columns["給与"];
				Console.WriteLine($"給与 : {column.DataType.ToString()}");
				column = dataTable.Columns["手当"];
				Console.WriteLine($"手当 : {column.DataType.ToString()}");
				column = dataTable.Columns["生年月日"];
				Console.WriteLine($"生年月日 : {column.DataType.ToString()}");

				// 列の正確なデータの取り出し
				string simei = row.Field<string>("氏名");
				Console.WriteLine(simei);
				int kyuyo = row.Field<int>("給与");
				Console.WriteLine(kyuyo);
				DateTime birth = row.Field<DateTime>("生年月日");
				Console.WriteLine($"{birth.ToShortDateString()}");

				// データのセット
				row["氏名"] = "山田 太郎";
				// 整数のセット
				row["給与"] = 10000;
				// NULL のセット
				row["手当"] = DBNull.Value;
				// 日付のセット
				row["生年月日"] = DateTime.Parse("1999/01/02");

				// 更新用のコマンドを取得
				adapter.UpdateCommand = commandBuilder.GetUpdateCommand();
				// 更新実行
				adapter.Update(dataSet);
			}

			// 一時停止
			Console.ReadLine();
		}
	}
}


更新の無い場合のデータ読み出し

接続準備等は同じなので、パラメータのセットの仕方を別バリエーションで行っています。
using System;
using System.Data.SqlClient;

namespace DBSelect
{
	class Program
	{
		static void Main(string[] args)
		{
			string connectionString;
			string queryString = "select * from 社員マスタ order by 社員コード";

			SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
			// 接続用のパラメータを追加
			builder.Add("Data Source", "layla");
			builder.Add("Initial Catalog", "lightbox");
			builder.Add("User ID", "sa");
			builder.Add("Password", "");

			// 接続文字列を取得
			connectionString = builder.ConnectionString;

			using (SqlConnection connection = new SqlConnection(connectionString))
			using (SqlCommand command = new SqlCommand())
			{

				// *********************
				// 接続
				// *********************
				connection.Open();
				// コマンドオブジェクトに接続をセット
				command.Connection = connection;
				// コマンドを通常 SQL用に変更
				command.CommandType = System.Data.CommandType.Text;

				// *********************
				// 実行 SQL
				// *********************
				command.CommandText = queryString;

				// *********************
				// レコードセット取得
				// *********************
				using (SqlDataReader reader = command.ExecuteReader())
				{

					// *********************
					// 列数
					// *********************
					int nCols = reader.FieldCount;

					// データ取得と表示
					int row_cnt = 0;
					while (reader.Read())
					{

						row_cnt++;

						// 初回のみ、タイトル文字列を設定
						if (row_cnt == 1)
						{
							for (int idx = 0; idx < nCols; idx++)
							{
								Console.Write($"{reader.GetName(idx)}  ");
							}
							Console.WriteLine();
						}

						// 行データ
						for (int idx = 0; idx < nCols; idx++)
						{

							// NULL でない場合
							if (!reader.IsDBNull(idx))
							{
								// 列のデータ型を取得
								Type fldType = reader.GetFieldType(idx);

								// 文字列
								if (fldType.Name == "String")
								{
									Console.Write($"{reader.GetValue(idx).ToString()}  ");
								}
								else if (fldType.Name == "Int32")
								{
									Console.Write($"{reader.GetInt32(idx)}  ");
								}
								else if (fldType.Name == "DateTime")
								{
									Console.Write($"{reader.GetDateTime(idx).ToShortDateString()}  ");
								}
								else
								{
									Console.Write($"{reader.GetValue(idx).ToString()}");
								}

							}
						}

						Console.WriteLine();

					}

					// リーダを使い終わったので閉じる
					reader.Close();

					connection.Close();
				}

			}       // 最外の using の終わり

			Console.ReadLine();
		}
	}
}




C#, データベース

さくらインターネットの phpMyAdmin でテーブルを作成してデータを追加する

さくらインターネットでは、MySQL のバージョンによって、phpMyAdmin のバージョンにも違いがあります。

1) MySQL 5.5 : phpMyAdmin のバージョン : 3.3.10.5
2) MySQL 5.7 : phpMyAdmin のバージョン : 4.7.9

以降は、phpMyAdmin のバージョンが 4.7.9 のサンプルです

▼ テーブルの作成は以下の SQL を実行すると可能ですが、phpMyAdmin を使用すれば対話式で作成ができます。
create table `クラス名称` (
	`コード` varchar(4)
	,`名称` varchar(100)
	,`担当` varchar(20)
	,primary key(`コード`)
)
▼ MySQL のバージョン表示をコンソールから行えます


▼ テーブル作成画面です


▼ 新規行の入力画面です


ツリーからテーブルを選択すると現在のデータが表示されるので、編集からさらに新規データを作成する事もできます




INSERT INTO `クラス名称`(`コード`, `名称`, `担当`) VALUES (':value1',':value2',':value3')

データをバインドさせて SQLを実行

SQL のデータ部分に :(コロン) を前に付加した変数を用意すると、バイントのチェックボックスによって入力フィールドが現れます。





VBScript で 32ビット ODBC ドライバの一覧を取得する( ODBC 接続のドライバ文字列を正しく取得したい )

Windows でデータベースに接続する際、ODBC データソースに登録せずに動的に利用する場合には、ドライバの正しい文字列が必要になリます。レジストリエディタで参照すればいいのですが、結構面倒なのでこのスクリプトを使えばすぐ取り出せます。

最初の『管理者として cscript 実行を強制する』は、cscript での実行を強制するついでに実装しています。(なんらかの制限環境でも動くようにとの考慮です。)

目的は、レジストリのキーの一覧ですが、キーの一覧は知る限り、WMI でしか取得できないので、GetObject("Winmgmts:root\default:StdRegProv") でレジストリ処理用のオブジェクトを取得して使用します。

一覧表示は、cscript で実行を強制しているので単純に Wscript.Echo で出力。コマンドプロンプトを新たに作成して実行するので、結果の表示を止めるために、Wscript.StdIn.ReadLine です。
' 管理者として cscript 実行を強制する
Set obj = Wscript.CreateObject("Shell.Application")
if Wscript.Arguments.Count = 0 then
	obj.ShellExecute "cscript.exe", WScript.ScriptFullName & " runas", "", "runas", 1
	Wscript.Quit
end if

const WMI_HKEY_LOCAL_MACHINE = &H80000002

Set objRegistry = GetObject("Winmgmts:root\default:StdRegProv")

strBasePath = "SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI"

Call objRegistry.EnumKey( WMI_HKEY_LOCAL_MACHINE, strBasePath, aKeys )

For Each strKeyPath in aKeys
	Wscript.Echo strKeyPath
Next

Wscript.StdIn.ReadLine

実際はいくつか変なのが混じっていますが ODBC 接続のドライバ文字列が欲しい場合を想定しているので、その場合はそれは排除して見れると思います。



※ コマンドプロンプトのプロパティで、簡易編集モードを ON にして、範囲をドラッグして右クリックでコピーできます。

※ コマンドプロンプトならば、『reg query HKLM\SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI』ですから、リダイレクトしてファイルに表示結果を書き込めばいいでしょう( 但し、キーが全て表示されるのでとても見にくいです )
reg query HKLM\SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI > list.txt

PHP で MySQL のクエリテストする為のコード( Bootstrap 仕様 )

$_GET['text'] で入力された SQL が引き渡されます。
※ GET コマンドなので、IE11 以外ならば SQLは アドレスバーで直接入力ができると思います。
※ php-mysql-test.php?text=SQL文

テーブルの表現には Bootstrap を使用しています( 一応スマホではテーブル部分のみ横スクロールします )

QueryString に text が無い場合と text に有効な文字が全く無い場合は  show variables でシステム変数の一覧を表示します
<?php
// キャッシュを使用しない
session_cache_limiter('nocache');
session_start();

// UTF-8
header( "Content-Type: text/html; charset=utf-8" );

?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<title>SQL実行結果</title> 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.css" />
<style>
/*
罫線等のテーブルのレイアウトは、Bootstrap にて適用
table {
	border: solid 1px #000;
	border-collapse: collapse;
}

th,td {
	border: solid 1px #000;
	padding: 5px;
}
*/
</style>
</head>
<body>
<!-- Bootstrap の alert でタイトル -->
<div class="alert alert-dark">
	MySQL Query TEST
</div>

<?php
if ( !isset( $_GET['text'] ) || trim($_GET['text']) == "" ) {
	// クエリ初期値は システム変数一覧
	$_GET['text'] = "show variables";
}

// P で挟んだデータの出力
print_cell_html( "p", $_GET['text'] );

$server = 'localhost';
$dbname = 'lightbox';
$user = 'root';
$password = 'パスワード';

// ***************************
// 接続
// ***************************
$mysqli = @ new mysqli($server, $user, $password, $dbname);
if ($mysqli->connect_error) {
	print "接続エラーです : ({$mysqli->connect_errno}) ({$mysqli->connect_error})";
	exit();
}

// ***************************
// クライアントの文字セット
// ***************************
$mysqli->set_charset("utf8"); 

// ***************************
// クエリ
// ***************************
$result = $mysqli->query($_GET['text']);
if ( !$result ) {
	print "\n";
	print "<span style='color:#f00'>error : " . $mysqli->error . "</span>";
	exit();
}

// ***************************
// 列数
// ***************************
$nfield = $result->field_count;
if ( $nfield ) {
	$ncount = 0;
	print "<div class='table-responsive-sm'>";
	print "<table class='table table-bordered table-hover'><thead class='thead-dark'>\n";

	// 行番号用タイトル
	print "\t<th></th>";

	// 列のタイトルを作成
	$field = $result->fetch_fields( );
	for( $i = 0; $i < $nfield; $i++ ) {

		// TH で挟んだデータの出力
		print_cell_html( "th", $field[$i]->name );

	}

	print "</thead>\n<tbody>\n";

	// ***************************
	// 行データ
	// ※ 結果の行を数値添字配列で取得
	// ***************************
	while ($row = $result->fetch_row()) {

		print "<tr>\n\t";
		// 行番号

		// TDで挟んだデータの出力
		print_cell_html( "td", ($ncount + 1) );

		for( $i = 0; $i < $nfield; $i++ ) {

			// TDで挟んだデータの出力
			print_cell_html( "td", $row[$i] );

		}
		print "\n</tr>\n";

		// 行番号
		$ncount++;
	}

	print "</tbody></table>";
	print "</div>";

}

// ***************************
// 接続解除
// ***************************
$mysqli->close();


// ***************************
// セルの HTML 出力関数
// ***************************
function print_cell_html( $html, $data ) {

print <<<CELL_HTML
<{$html}>{$data}</{$html}>
CELL_HTML;

}

?>

</body>
</html>




Pleiades Ultimate の XAMPP 内の MySQL を利用可能にしてテストデータを登録する

xampp-control.exe の設定

xampp-control.exe は管理者権限で実行する必要があるので、エクスプローラから右クリックしてプロパティの『互換性』タブで管理者として実行するチェックを ON にします。



my.ini の設定( サーバーをUTF-8 に設定 )



C:\pleiades\xampp\mysql\bin\my.ini の以下の部分のコメントを削除します。



開発用のソフトウェアを準備

SQLの窓 Build C++ と、販売管理C でテスト環境を構築します 。

手順1 ( MySQL の ODBC ドライバ)

SQLの窓 Build C++ は 32ビットアプリケーションなので、まず MySQL の ODBC ドライバ(32ビット)をダウンロードしてインストールします。

Connector/ODBC 5.3

※ 何も選択せずにダイアログ内で進めればOK です
Visual Studio 2013 の Visual C++ 再頒布可能パッケージ

Connector/ODBC 8.0
Microsoft Visual C++ 2015 再頒布可能パッケージ Update 3


手順2 (SQLの窓 Build C++)

次に、SQLの窓 Build C++ をダウンロードして解凍して WinOfSql.exe を実行して下さい。

※ レジストリは使用しません。
※ 複数のフォルダにいくつあっても動作します。
※ 削除すればアンインストールです。

実行後 M ボタンをクリックして MySQL 接続用のダイアログを開き、ODBC アドミニストレータボタンで ODBC の DSN を作成する Windows の管理ツール(32ビット) を実行します。



手順3 ( DSN 登録 )

ここで、xampp-control.exe を実行し、開始ボタンで MySQL を開始します。(初期設定なので失敗しないようにこのタイミングで実行しています / 以降は必要な時でいいです)



ユーザDSN => 追加 => MySQL ODBC 5.3 Unicode Driver

( ODBC32ビットドライバの一覧は、HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI より確認できます)

▼ Details ボタンで全て開いて Character Set で cp932 を選択して下さい。


データベースは、まだユーザ用を作成していないので mysql を選択します。これは後で変更しなくとも、接続時に変更しますのでこのままでいいです。

入力が終わったら、データベースの右の Test ボタンで接続が成功するのを確認します。接続に成功したら、OK で登録します。

手順4 ( SQLの窓 Build C++ で接続して DB 作成 )



M ボタンで接続ダイアログを表示して、DSN に登録した情報で接続します



右側のテキストエリアで create database 自分用のデータベース名 で、Action ボタンをクリックして作成します。





作成後は、いったん終了して再度 SQLの窓 Build C++ を実行します(オペミスを防ぐためです)。そして再度 M ボタンで、今度は作成したデータベース(ここでは lightbox)で接続します。( 接続情報を保存する為です )




手順5 ( 作成した データーベース の確認 )

接続後、テーブルが無いのでなにも表示されませんが、メニューに登録済みの SQL で内容を確認できます。

『データベース一覧』で、登録したデータベースと既に存在するデータベースを確認できます。





『システム変数の値』で、キャラクタセットを確認します





手順6 ( 販売管理C.mdb をインポート )

▼ 学習用 MDB データのダウンロード


解凍した中にある 販売管理C.mdb を SQLの窓 Build C++ の左側のリストにドラッグ&ドロップします。



次にリストの中のテーブルを、SHIFTキーを使って選択して(まず先頭をクリックして、SHIFTキーを押しながら最後をクリック)から、処理 => エクスポート => MySQL を選択



直前の接続が選択されているので、下欄のチェックボックスを二つ選択して実行します


※ チェックボックスが無いと、主キーが無い状態でデータのみがエクスポートされます( 後からキー設定は可能ですがテーブルを全て設定するのは面倒です )

完了すると左下にメッセージが出るので、x ボタンで閉じます。



閉じたら、そこは MDB の接続なので、M ボタンで切り替えて下さい。テーブルの一覧が表示されるはずです。

※ テーブルをダブルクリックすると、テーブルデータが表示されて直接変更が可能です。( 更新は 『編集』メニューから更新です )







関連する記事

Pleiades Eclipse 4.7 Oxygen 2 Windows 64bit Ultimate Full Edition のインストールといろいろな準備


Pleiades Oxygen 2 の XAMPP 内の FileZilla Server をインストールして使用する


Pleiades Eclipse 4.7 Oxygen で Python を使って MySQL にアクセスする





SQLServer : 前月データを抽出する条件

まず、dateadd と datepart の機能を確認する為の SQL が以下のようになります。

※ m と mm は month の省略形です
select
	cast('2019/01/01' as datetime),
	dateadd(month, -1, getdate()),
	dateadd(m, -1, getdate()),
	dateadd(mm, -1, getdate()),

	case
	when datepart(year, cast('2019/01/01' as datetime)) = datepart(year, dateadd(month, -1, getdate()))
	 	then '一致しました'
		else '一致しません'
	end as 年比較,

	case
	when datepart(month, cast('2019/01/01' as datetime)) = datepart(month, dateadd(month, -1, getdate()))
	 	then '一致しました'
		else '一致しません'
	end as 月比較

▼ これを踏まえて条件にしたものです。
select *

from [テーブル名]

where
	DATEPART(year, 対象日付) = DATEPART(year, DATEADD(m, -1, GETDATE()))
and	DATEPART(m, 対象日付) = DATEPART(m, DATEADD(m, -1, GETDATE()))


現在の年月日を getdate() で取得し、その月を一つマイナスして年部分と月部分を別々に取得して、比較したい日付の年部分と月部分がどちらも一致していたら、前月です。


関連する Microsoft ドキュメント

DATEADD (Transact-SQL)

DATEPART (Transact-SQL)

CAST および CONVERT (Transact-SQL)

CASE (Transact-SQL)




Microsoft® SQL Server® Express のダウンロードとインストール

Microsoft® SQL Server® 2012 Express
Microsoft® SQL Server® 2014 Express
Microsoft® SQL Server® 2016 Service Pack 2 Express
Microsoft® SQL Server® 2017 Express

バージョン、エディション、および SQL Server の更新プログラム レベルとそのコンポーネントを確認する方法

以下は Microsoft® SQL Server® 2012 Express をインストール時のキャプチャです


















参考情報

SQLExpress 2005( および 2008 ) の接続設定