oracle 11g XE でキャラクタセットを変更した時のメモ

Oracleを使ったシステムの改修の仕事でサーバーに無償版のOracle 11g XEをインストールして、
先方から提供されたダンプファイルをインポートしたところ、
「ORA-12899: 列”XX”の値が大きすぎます(実際: XX、最大: XX)」といったエラーが頻発してしまいました。
インストールしたXEのデータベースキャラクタセットがUTF8だったのに元はSJISであることが原因でした。
データベースキャラクタセットの変更なんてコマンド1発だろうと思っていたらえらい大変でした。
ここを参考に(というかほぼそのまま)作業した内容を備忘のため書き留めておくことにします。
自分の環境に合わせて若干(ディレクトリ名等)変更しています。
■インスタンスの削除

>cleanup.bat
(サービスの停止、インスタンスの削除をしてくれます)

■不要なファイルの削除

C:\oraclexe\app\oracle\product\11.2.0\server\dbs\*
C:\oraclexe\app\oracle\product\11.2.0\server\database\*(oradba.exe以外)
C:\oraclexe\app\oracle\oradata\XE\*

■インスタンスの作成
・以下をC:\oraclexe\app\oracle\product\11.2.0\server\database\initXE.oraとして保存

java_pool_size=4194304
large_pool_size=4194304
shared_pool_size=62914560
streams_pool_size=0
audit_file_dest='C:\oraclexe\app\oracle\admin\XE\adump'
compatible='11.2.0.1.0'
control_files='C:\oraclexe\app\oracle\oradata\XE\control.dbf'
core_dump_dest='C:\oraclexe\app\oracle\admin\XE\cdump'
db_name='XE'
dispatchers='(PROTOCOL=TCP) (SERVICE=XEXDB)'
job_queue_processes=2
open_cursors=300
os_authent_prefix=''
pga_aggregate_target=40M
remote_login_passwordfile='EXCLUSIVE'
sessions=20
sga_target=140M
shared_servers=1
undo_management='AUTO'
undo_tablespace='UNDO'

・oradimユーティリティを実行し、インスタンスを作成

oradim -NEW -SID XE -SYSPWD manager -PFILE C:\oraclexe\app\oracle\product\11.2.0\server\database\initXE.ora

■インスタンス起動

>set ORACLE_SID=XE
>sqlplus / as sysdba
(アイドル・インスタンスに接続しました)
SQL>startup nomount pfile=C:\oraclexe\app\oracle\product\11.2.0\server\database\initXE.ora
(ORACLEインスタンスが起動しました)

・以下の内容をファイルC:\oraclexe\app\oracle\product\11.2.0\server\database\createDB.oraに保存

create database XE
logfile group 1 ('C:\oraclexe\app\oracle\oradata\XE\redo1.dbf') size 32M,
group 2 ('C:\oraclexe\app\oracle\oradata\XE\redo2.dbf') size 32M,
group 3 ('C:\oraclexe\app\oracle\oradata\XE\redo3.dbf') size 32M
character set JA16SJIS
national character set utf8
datafile 'C:\oraclexe\app\oracle\oradata\XE\system.dbf'
size 240M
autoextend on
next 16M maxsize unlimited
extent management local
sysaux datafile 'C:\oraclexe\app\oracle\oradata\XE\sysaux.dbf'
size 48M
autoextend on
next 8M
maxsize unlimited
undo tablespace undo
datafile 'C:\oraclexe\app\oracle\oradata\XE\undo.dbf'
size 48M
autoextend on
default temporary tablespace temp
tempfile 'C:\oraclexe\app\oracle\oradata\XE\temp.dbf'
size 8M
autoextend on;

■データベースを作成(sqlplus内)

SQL>@C:\oraclexe\app\oracle\product\11.2.0\server\database\createDB.ora
(データベースが作成されました)

・カタログ定義スクリプトの実行

SQL>@C:\oraclexe\app\oracle\product\11.2.0\server\RDBMS\ADMIN\catalog.sql

・PL/SQLパッケージ作成スクリプトの実行(かなり時間がかかります)

SQL>@C:\oraclexe\app\oracle\product\11.2.0\server\RDBMS\ADMIN\catproc.sql

・SYSTEMで接続し、PRODUCT_USER_PROFILE表に対するSELECT権限をPUBLICに付与

SQL>connect system/manager
SQL>@C:\oraclexe\app\oracle\product\11.2.0\server\sqlplus\admin\pupbld.sql

■確認

SELECT PARAMETER, VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER LIKE '%CHARACTERSET%';

以上でした。
■追記:クライアントの文字コード

システム環境変数「NLS_LANG」の値として「JAPANESE_JAPAN.JA16SJISTILDE」とします。

CakePHPで不達メールの一覧を取得するモデルを作ってみた

お問い合わせフォームからメールを送信することもままあると思いますが、
不達メールの問題はついて回るかと思います。
そこでPOP3でメールサーバに接続し不達メールの一覧を取得するモデルを作ってみました。
[PHP]
/**
* 不達メールモデル
*/
class BounceMail extends AppModel {
var $useTable = false;
var $name = ‘BounceMail’;

var $mboxconnstr = “{メールサーバーホスト名:110/pop3}INBOX”;
var $user = “ユーザー名”;
var $passwd = “パスワード”;
var $subject = “Undelivered Mail Returned to Sender”;

function find($conditions = null, $extra = array()) {
$records = array();
$mbox = imap_open($this->mboxconnstr, $this->user, $this->passwd);
if ($mbox == false) {
return $records;
}
$mail_check = imap_check($mbox);
for($i=1;$i<=$mail_check->Nmsgs;$i++) {
$headinfo = imap_headerinfo($mbox, $i);
$bodyinfo = imap_body($mbox, $i);
if ($headinfo->Subject == $this->subject) {
$rtn = preg_match(“/<.+@.+?>/”, $bodyinfo, $rslt);
if ($rtn == true) {
if (is_array($rslt)) {
foreach($rslt as $key=>$val) {
if (!empty($conditions)) {
foreach($conditions as $condition){
// 日付範囲指定の条件
if (isset($condition[‘dateFrom’])) {
if (date(“Ymd”, strtotime($headinfo->date)) < date("Ymd", strtotime($condition['dateFrom']))) { continue 2; } } if (isset($condition['dateTo'])) { if (date("Ymd", strtotime($headinfo->date)) > date(“Ymd”, strtotime($condition[‘dateTo’]))) {
continue 2;
}
}
}
}
$records[$i][“datetime”] = date(“Y-n-j H:i:s”, strtotime($headinfo->date));
$records[$i][“mail”] = rtrim(ltrim($val, “<"), ">“);
break;
}
}
}
}
}
imap_close($mbox);
return $records;
}

function paginateCount($conditions = null, $recursive = 0, $extra = array()) {
$rslt = $this->find($conditions, $extra);
$count = count($rslt);
return count($rslt);
}

function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) {
$rslt = $this->find($conditions, $extra);
$records = array();
$end = $page * $limit;
$start = $end – $limit + 1;
$i = 0;
foreach($rslt as $row){
if (++$i >= $start && $i <= $end) { $records[] = $row; } } return $records; } } [/PHP]

Chrome フォーム再送信の確認

セッション使っている時に戻るボタン押下で出る「フォーム再送信の確認」。
解決策をとりあえずメモ。
session_start()する前に、session_cache_limiter(‘none’)とする
あまりお行儀のよい方法ではないらしい。

Googleカレンダーから祝日を取得して配列に展開するコンポーネントを作ってみた。

ここを参照して作ってみました。
国については適宜追加してください。
[PHP]
class HolidayComponent extends Object {
/**
* 指定年の祝日リストを配列で取得します。
*/
function getHoliday($year = null, $country = ‘ja’){
$ret = array();;
if(empty($year)){
$dateBegin = date( “Y-m-01” );
$dateEnd = date( “Y-m-t” );
}else{
$dateBegin = date( “Y-01-01”, mktime( 0, 0, 0, 1, 1, $year ) );
$dateEnd = date( “Y-12-t”, mktime( 0, 0, 0, 12, 1, $year ) );
}
$query = “start-min=” . $dateBegin . “&start-max=” . $dateEnd . “&max-results=100”;
switch($country){
case ‘ja’:
$feed = “http://www.google.com/calendar/feeds/japanese__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
case ‘us’:
$feed = “http://www.google.com/calendar/feeds/usa__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
case ‘uk’:
$feed = “http://www.google.com/calendar/feeds/uk__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
case ‘ch’:
$feed = “http://www.google.com/calendar/feeds/china__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
case ‘ph’:
$feed = “http://www.google.com/calendar/feeds/philippines__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
default :
$feed = “http://www.google.com/calendar/feeds/japanese__ja@holiday.calendar.google.com/public/full” . “?” . $query;
break;
}

$xml = simplexml_load_file( $feed );
if(!$xml){
return $ret;
}
$ii = 0;
foreach( $xml->entry as $entry ){
$gd = $entry->children( “http://schemas.google.com/g/2005” );
$attributes = $gd->when->attributes();
foreach( $attributes as $name => $value ){
if( $name == “startTime” ){
$ret[$ii][‘date’] = “”.$value.””;
$ret[$ii][‘title’] = “”.$entry->title.””;
$ii++;
break;
}
}
}
usort($ret, array($this, “_cmp”));
return $ret;
}
/**
* 指定年の祝日リスト配列のソート
*/
function _cmp($a, $b) {
if ($a[‘date’] == $b[‘date’]) {
return 0;
}
return ($a[‘date’] < $b['date']) ? -1 : 1; } } [/PHP]

ロりポップでsubversion

チカッパプランでSSHが使えてsvn関連のコマンドを使えるのでリポジトリを作ってみる。

サーバー側

1.リポジトリ用のディレクトリを作成。
mkdir -p repos/hoge
2.リポジトリを初期化
svnadmin create repos/hoge --fs-type fsfs
3.trunk、branchs、tagsを作成
svn mkdir file://[フルパス]/repos/hoge/trunk -m "create trunk."
svn mkdir file://[フルパス]/repos/hoge/branchs -m "create branchs."
svn mkdir file://[フルパス]/repos/hoge/tags -m "create tags."

続いてクライアント側(TortoiseSVNを使用)

1.SSHクライアントの設定

TortoiseSVN同梱の「TortoisePlink.exe」(SSHクライアント)を利用
[TortoiseSVN]→[設定]→[ネットワーク]のSSHクライアントに

"C:\Program Files\TortoiseSVN\bin\TortoisePlink.exe" -P [接続ポート番号] -l [SSHアカウント] -pw [SSHパスワード]
2.チェックアウト

空フォルダを作りチェックアウト。
[TortoiseSVN]→[チェックアウト]
その際のリポジトリのURLは

svn+ssh://[SSHアカウント]@[SSHサーバー]/[リポジトリまでの絶対パス]/trunk
3.チェックアウトしたフォルダにバージョン管理するフォルダ、ファイルをコピー
4.コミット

これでいけるようです。

Backlogでsubversionの備忘

バージョン管理を始める際にやること。
1.Backlog上にリポジトリを作る。
2.自分のPCにsubversion用に空のフォルダを作る。
3.空のフォルダでチェックアウト。
4.チェックアウトしたフォルダにバージョン管理するフォルダ、ファイルをコピー
5.コミット
当たり前のことなんですが、いつもまごまごしてしまうのでメモしておきます。

CakePHPで普通のHtmlやPHPを配置する

ガッチリできあがったCakePHPで作成したサイトがあるとして、他で作った「普通に」作った簡単な問い合わせフォーム的なものをサブディレクトリに配置したい場合って結構あると思います。
その時は「.htaccess」を細工すればOK。
元の.htaccessが


	RewriteEngine On
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

で、普通のHtmlファイルを配置したいサブディレクトリを「XXXX」とすると


	RewriteEngine On
	RewriteBase /
	RewriteCond %{REQUEST_URI} ^/XXXX/(.*)$
	RewriteRule ^.*$ - [L]

を先頭に追加して以下のようにする。


	RewriteEngine On
	RewriteBase /
	RewriteCond %{REQUEST_URI} ^/XXXX/(.*)$
	RewriteRule ^.*$ - [L]

# Begin CakePHP

	RewriteEngine On
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

参照元はこちら。