SQLの窓

2014年04月13日


PHP + MySQL : Windows における ODBC 経由での接続とデータの取得(SELECT)

MySQL の Windows における ODBC ドライバは、既存の SHIFT_JIS ベースの古いアプリケーシヨンの為に、charset 変更できるのがデータ部分だけとなっていました。こちらから送る SQL 内のキャラクタセットは 日本語環境においては SHIFT_JIS でやりとりするような前提で設計されているようです。

ですから、PHP で利用するとなると、ソースコードを SHIFT_JIS として、ドライバの charset を cp932 にすると全て日本語環境でうまくいくようになっています。もし、UTF-8 ベースで PHP のコードを書く必要がある場合は、charset を utf8 にすると、データは正しく utf8 で読み込めます。ただ、SQL を SHIFT_JIS で書く必要がありますし、列名(連想配列内)は SHIFT_JIS なので、mb_convert_encoding で変換する必要があります。

PDO_ODBC > ODBC 関数

ODBC 関数は、古くからある関数で、他の MySQL 関数に比べると実装(機能)が分散されていて、同じ処理をする場合にコード量が増えてしまいます。しかし、SQLServer に接続して処理を行う場合は信頼性が高いようです。( SQLServer 用の ODBC ドライバは選択肢としてとても有効だと思います )

ただ、MySQL をターゲットとする場合は、わさわざ ODBC を選ぶ必要はほとんどありません。

ODBC 関数
<?php
header( "Content-Type: text/html; Charset=shift_jis" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

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

$connect_string = "Provider=MSDASQL;";
$connect_string .= "Driver={MySQL ODBC 5.3 Unicode Driver};";
$connect_string .= "Server={$server};";
$connect_string .= "DATABASE={$db_name};";
$connect_string .= "UID={$user};";
$connect_string .= "PWD={$password};";
$connect_string .= "charset=cp932;";
// このキャラクタ設定は、サーバーからのキャラクタセット
// クライアントは SHIFT_JIS が前提で、インストールされた PCに依存しているようです。

// 接続
$connect = @odbc_connect($connect_string, "", "");
if ( !$connect ) {
	die("接続エラーです : " . odbc_errormsg() );
}

// クエリ
$result = @odbc_exec($connect,"select * from 社員マスタ");
if ( !$result ) {
	die('クエリーに誤りがあります : ' . odbc_errormsg() );
}

// 列数
$field_count = odbc_num_fields( $result );
$count = 0;

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<style>
* {
	font-family: "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 12px;
}
table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
	background-color: #FFFFFF;
}
td {
	padding: 5px;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
}
</style>
</head>
<body>

<?php
print $connect_string;

$log_file = "rowdata_003.log";

file_put_contents( $log_file,"" );

print "<table>\n";
while (odbc_fetch_into($result,$row)) {
	print "<tr>\n";
	print "\t<td>" . ($count + 1) . "</td>\n";
	for( $i = 0; $i < $field_count; $i++ ) {
		print "\t<td>{$row[$i]}</td>\n";
	}
	print "</tr>\n";
	$count++;
	file_put_contents( $log_file, print_r($row,true), FILE_APPEND );
}
print "</table>";

// メモリを開放ですが、通常は必要ありません
odbc_free_result($result);

// 接続解除
odbc_close($connect);
?>

<br>
出力件数 : <?= $count ?>


PDO_ODBC
<?php
header( "Content-Type: text/html; Charset=shift_jis" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

$conf = array(
	"driver" => "{MySQL ODBC 5.3 Unicode Driver}",
	"server" => "localhost",
	"db" => "lightbox",
	"user" => "root",
	"pass" => "パスワード",
	"charset" => "cp932"
);

// **********************************************************
// 接続
// **********************************************************
try {
	$connect = new PDO(
		"odbc:Driver={$conf['driver']};Server={$conf['server']};" .
		"Database={$conf['db']};Uid={$conf['user']};Pwd={$conf['pass']};".
		"charset={$conf['charset']}");
}
catch ( Exception $ex ) {
	die( '{"error": "接続できませんでした: ' . $ex->getMessage() . '"}' );
}

// **********************************************************
// 結果セット
// **********************************************************
$rs = $connect->query( "select * from 社員マスタ" );
if ( $rs === false ) {
	$er = $connect->errorInfo();
	die('{ "error" : "' . $er[2] . '" }');
}

// フィールド数
$field_count = $rs->columnCount();
$count = 0;

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<style>
* {
	font-family: "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 12px;
}
table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
	background-color: #FFFFFF;
}
td {
	padding: 5px;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
}
</style>
</head>
<body>

<?php
print $connect_string;

$log_file = "rowdata_004.log";

file_put_contents( $log_file,"" );

print "<table>\n";
while ($row = $rs->fetch(PDO::FETCH_BOTH)) {
	print "<tr>\n";
	print "\t<td>" . ($count + 1) . "</td>\n";
	for( $i = 0; $i < $field_count; $i++ ) {
		print "\t<td>{$row[$i]}</td>\n";
	}
	print "</tr>\n";
	$count++;
	file_put_contents( $log_file, print_r($row,true), FILE_APPEND );
}
print "</table>";

$rs->closeCursor();
?>

<br>
出力件数 : <?= $count ?>



関連する記事

posted by lightbox at 2014-04-13 17:03 | MySQL | このブログの読者になる | 更新情報をチェックする

PHP + MySQL : PDO_MySQL での接続とデータの取得(SELECT)

mysqli は、手続き型もあり、クラスとして利用はできますが、立ち位置としては中間的な存在でした。しかし、PDO では、多くのデータベースに対して同じ処理を実現する(インターフェイス)為に作成されたものですから、本来の『オブジェクト指向型』として利用するといいと思います。

コンストラクタの実行で、PDO は、指定されたデータベースへの接続に失敗した場合、 PDOException を投げます。( ここでは、Exception として一般的に使用しています )

closeCursor メソッドは、カーソルを閉じてステートメントを再実行できるようにするもので、多くの処理を実行する時に必要になって来るものです。

また、接続を閉じる処理はメソッドとして存在しておらず、インスタンスに NULL をセットするようマニュアルで明示されています
接続を閉じるには、他から 参照されていないことを保障することでオブジェクトを破棄する 必要があります。それには、オブジェクトを保持している変数に対して NULL を代入します
▼ この接続でのキャラクタセットの情報
character_set_clientutf8
character_set_connectionutf8
character_set_databaseutf8
character_set_filesystembinary
character_set_resultsutf8
character_set_serverutf8
character_set_systemutf8
<?php
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

$conf = array(
	"server" => "localhost",
	"db" => "lightbox",
	"user" => "root",
	"pass" => "パスワード"
);

// **********************************************************
// 接続
// **********************************************************
try {
	$connect = new PDO("mysql:host={$conf['server']};dbname={$conf['db']}",
		$conf['user'], $conf['pass'] );
}
catch ( Exception $ex ) {
	die( '{"error": "接続できませんでした: ' . $ex->getMessage() . '"}' );
}

// **********************************************************
// 結果セット
// **********************************************************
$rs = $connect->query( "select * from 社員マスタ" );
if ( $rs === false ) {
	$er = $connect->errorInfo();
	die('{ "error" : "' . $er[2] . '" }');
}

// フィールド数
$field_count = $rs->columnCount();
$count = 0;

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
* {
	font-family: "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 12px;
}
table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
	background-color: #FFFFFF;
}
td {
	padding: 5px;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
}
</style>
</head>
<body>

<?php
print $connect_string;

$log_file = "rowdata_005.log";

file_put_contents( $log_file,"" );

print "<table>\n";
while ($row = $rs->fetch(PDO::FETCH_BOTH)) {
	print "<tr>\n";
	print "\t<td>" . ($count + 1) . "</td>\n";
	for( $i = 0; $i < $field_count; $i++ ) {
		print "\t<td>{$row[$i]}</td>\n";
	}
	print "</tr>\n";
	$count++;
	file_put_contents( $log_file, print_r($row,true), FILE_APPEND );
}
print "</table>";

$rs->closeCursor();
?>

<br>
出力件数 : <?= $count ?>



関連する記事

posted by lightbox at 2014-04-13 02:12 | MySQL | このブログの読者になる | 更新情報をチェックする

PHP + MySQL : MySQL 改良版拡張モジュール mysqli クラスでの接続とデータの取得(SELECT)

マニュアル上は、『新しくコードを書くときには mysqli や PDO_MySQL を使うべきです。』とあります。基本的な部分は MySQL 関数とさほど変わり無く、非常に使いやすいクラスです。( 手続き型も存在しますが、PDO と比較する意味でも、オブジェクト指向型のほうが自然です )

コンストラクタに、データベース名も指定するので、MySQL 関数 より接続部分だけを取ってもシンプルに変化します。

結果のログも utf8n で出力され、MySQL 関数の結果と同じです。

fetch_array メソッドは、省略すると第二引数は MYSQLI_BOTH を指定した事になりますが、ここでは明示しています。( MYSQLI_ASSOC、 MYSQLI_NUM あるいは MYSQLI_BOTH. のいずれかを指定できます )

▼ この接続でのキャラクタセットの情報
character_set_clientutf8
character_set_connectionutf8
character_set_databaseutf8
character_set_filesystembinary
character_set_resultsutf8
character_set_serverutf8
character_set_systemutf8
<?php
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

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

// 接続
$connect = @ new mysqli($server, $user, $password, $db_name);
if ($connect->connect_error) {
	die('Connect Error (' . $connect->connect_errno . ') '
	. $connect->connect_error);
}

// クエリ
$result = $connect->query("select * from 社員マスタ"); 
if ( !$result ) {
	die('クエリーに誤りがあります : ' . $connect->error );
}

// 列数
$field_count = $connect->field_count;
$count = 0;

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
* {
	font-family: "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 12px;
}
table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
	background-color: #FFFFFF;
}
td {
	padding: 5px;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
}
</style>
</head>
<body>

<?php

$log_file = "rowdata_002.log";

file_put_contents( $log_file,"" );

print "<table>\n";
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
	print "<tr>\n";
	print "\t<td>" . ($count + 1) . "</td>\n";
	for( $i = 0; $i < $field_count; $i++ ) {
		print "\t<td>{$row[$i]}</td>\n";
	}
	print "</TR>\n";
	$count++;
	file_put_contents( $log_file, print_r($row,true), FILE_APPEND );
}
print "</table>";

// 開放
$result->close();

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

?>

<br>
出力件数 : <?= $count ?>



関連する記事

posted by lightbox at 2014-04-13 01:37 | MySQL | このブログの読者になる | 更新情報をチェックする

2014年04月12日


PHP + MySQL : PHP 5.5.0 で非推奨の MySQL 関数での接続とデータの取得(SELECT)

PHP のマニュアルでは、 MySQLi や PDO_MySQL を使うように推奨していますが、当分このコードも扱えないといけないので、一番扱いやすい内容でまとめました。

フィールドの数を mysql_num_fields で取得して、mysql_fetch_array で 連想配列、添字配列として結果の行を取得しています。

file_put_contents の追加モードでログを出力しています( utf-8n で出力されます )

MySQL のキャラクタセットは UTF-8 です。PHP のページも UTF-8 なので、特別な考慮なしに正しく表示されます。

▼ この接続でのキャラクタセットの情報
character_set_clientutf8
character_set_connectionutf8
character_set_databaseutf8
character_set_filesystembinary
character_set_resultsutf8
character_set_serverutf8
character_set_systemutf8
<?php
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

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

// 接続
$connect = @mysql_connect( $server, $user, $password );
if ( !$connect ) {
	die("接続エラーです : " . mysql_error() );
}

// DB選択
if ( !mysql_select_db( $db_name, $connect ) ) {
	die("DB選択に誤りがあります : " . mysql_error() );
}

// クエリ
$result = mysql_query("select * from 社員マスタ", $connect);
if ( !$result ) {
	die('クエリーに誤りがあります : ' . mysql_error());
}

// 列数
$field_count = mysql_num_fields( $result );
$count = 0;

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
* {
	font-family: "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 12px;
}
table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
	background-color: #FFFFFF;
}
td {
	padding: 5px;
	border-style: solid;
	border-color: #c0c0c0;
	border-width: 1px;
}
</style>
</head>
<body>

<?php

$log_file = "rowdata_001.log";

file_put_contents( $log_file,"" );

print "<table>\n";
while ($row = mysql_fetch_array($result)) {
	print "<tr>\n";
	print "\t<td>" . ($count + 1) . "</td>\n";
	for( $i = 0; $i < $field_count; $i++ ) {
		print "\t<td>{$row[$i]}</td>\n";
	}
	print "</tr>\n";
	$count++;
	file_put_contents( $log_file, print_r($row,true), FILE_APPEND );
}
print "</table>";

// メモリを開放ですが、通常は必要ありません
mysql_free_result($result);

// 接続解除
mysql_close($connect);
?>

<br>
出力件数 : <?= $count ?>

"select * from 社員マスタ" とありますが、厳密には "select * from `社員マスタ`" のように使う事ができます( これは、Oracle の "社員マスタ" にあたり、Microsoft では [社員マスタ] にあたります。

▼ ログ( rowdata_001.log / utf8n )
Array
(
    [0] => 0001
    [社員コード] => 0001
    [1] => 浦岡 友也
    [氏名] => 浦岡 友也
    [2] => ウラオカ トモヤ
    [フリガナ] => ウラオカ トモヤ
    [3] => 0003
    [所属] => 0003
    [4] => 0
    [性別] => 0
    [5] => 2014-04-11 00:00:00
    [作成日] => 2014-04-11 00:00:00
    [6] => 2014-06-27 00:00:00
    [更新日] => 2014-06-27 00:00:00
    [7] => 270000
    [給与] => 270000
    [8] => 9000
    [手当] => 9000
    [9] => 
    [管理者] => 
    [10] => 
    [生年月日] => 
)


関連する記事

posted by lightbox at 2014-04-12 23:57 | MySQL | このブログの読者になる | 更新情報をチェックする

Seesaa のタグページの「タグクラウド」のリンク先を一覧表示( ドメイン/tag/articles/タグ名 )に変更する

シーサーのブログでは、ドメイン/tag/タグ名 という URL でタグページに移動して、タグクラウドから、タグを含んだ記事の一覧を表示してくれるのですが、最初のリンクでは、一覧表示数が何故か限定されていて、使いにくいものになっています。

そこで、最初から「次のページ」へ移動可能な一覧ページのリンクに JavaScript で変更してしまいます。( ドメイン/tag/articles/タグ名 )

HTML のテンプレートの真ん中くらいにあるので、tag_cloud("tag_cloud"); の後に以下のコードの該当部分をコピーしてやると、とても使いやすくなると思います。
<% if:page_name eq 'tag' -%>
<div class="tag">
<script type="text/javascript" language="javascript" src="<% site_info.blog_url %>/js/tag_cloud.js"></script>
<div id="tag_cloud">
<% loop:list_tags -%><a href="<% blog.tag_url(tag) %>" class="_tag" title="<% tag.word | html %>/<% count %>"><% tag.word | html %></a>
<% /loop -%>
</div>
<script type="text/javascript" language="javascript"><!--
tag_cloud("tag_cloud");
var tag_base = document.getElementById("tag_cloud");
var tag_target = tag_base.getElementsByTagName("a");
var tag_len = tag_target.length;
var tag_href = "";
for( var tag_i = 0; tag_i < tag_len; tag_i++ ) {
	if ( tag_target[tag_i].className == '_tag' ) {
		tag_href = tag_target[tag_i].href;
		tag_href = tag_href.replace("\/tag\/","/tag/articles/");
		tag_target[tag_i].href = tag_href;
	}
}
--></script>
<br />

また、記事毎に付加されているタグにも実装したい場合は、article.id を使用して記事毎のタグを表示する領域の id をユニークにする必要があります。

▼ 記事コンテンツ内のコード
<% if:list_tag %><div id="tag_base<% article.id %>" class="tag-word">タグ:<% loop:list_tag %><a href="<% blog.tag_url(tag) %>"><% tag.word %></a> <% /loop %>
</div>
<script type="text/javascript" language="javascript"><!--
var tag_base = document.getElementById("tag_base<% article.id %>");
var tag_target = tag_base.getElementsByTagName("a");
var tag_len = tag_target.length;
var tag_href = "";
for( var tag_i = 0; tag_i < tag_len; tag_i++ ) {
	tag_href = tag_target[tag_i].href;
	tag_href = tag_href.replace("\/tag\/","/tag/articles/");
	tag_target[tag_i].href = tag_href;
}
--></script><% /if %>





Seesaa独自タグ簡易リファレンス

タグ:Seesaa javascript
posted by lightbox at 2014-04-12 04:01 | Seesaa プログ管理支援 | このブログの読者になる | 更新情報をチェックする

2014年04月05日


レジストリ : ごみ箱を無効にする

Windows7 の設定

▼ ユーザ単位
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
NoRecycleFiles(DWORD) を 1 に設定

NoRecycleFiles の設定も有効ですが、ドライブ単位で NukeOnDelete の設定が可能です。これは、レジストリからでは無く、「ごみ箱」のプロパティより設定できます。 NoRecycleFiles を設定すると、この設定変更が使用できなくなって、規定でごみ箱が使えない事を示しています( 削除と同時にファイルを消去する設定になっています ) この変更(NoRecycleFiles=1)は、エクスプローラを再起動すると反映されます( またはログオフ ) ▼ エクスプローラを再起動するスクリプト
' 起動用
Set WshShell = CreateObject( "WScript.Shell" )
' WMI用
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

' いったん終了させます
Set colProcessList = objWMIService.ExecQuery _ 
	("Select * from Win32_Process Where Name = 'explorer.exe'") 
For Each objProcess in colProcessList
	on error resume next
	objProcess.Terminate() 
	on error goto 0
Next 

' 少し待ちます
Wscript.Sleep(500)
Call WshShell.Run( "explorer.exe" )


Windows XP

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
NoRecycleFiles(DWORD) を 1 に設定

ユーザ単位の設定場所 上のリンクからダウンロードできるスクリプトを実行すると開く場所に、DWORD で NoRecycleFiles として 1 を設定。( Explorer キーが無い場合は作成します ) Windows 全体で設定 上のリンクからダウンロードできるスクリプトを実行すると開く場所に、DWORD で NukeOnDelete として 1 を設定。これは以下の設定でセットされます。 Gomibako3
タグ:Windows ごみ箱
posted by lightbox at 2014-04-05 15:37 | Windows | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり