データベースの最近のブログ記事

さて、無事に Oracle Database 21c Express Edition (XE) のインストールが終了

具体的にテスト用(お勉強用)の TABLE などを作っていきたいが、Windows 上で CUI 環境の sqlplus でゴリゴリやるのもなあ・・・いや、実際、UNIX 互換界隈では PostgreSQL を CUI 環境の psql とかでゴリゴリやってるんだけど、あれは Putty とか TeraTerm のようなターミナルソフトの上で zsh といったシェルを操作するから成り立っているのであって、Windows の Terminal の上で(PowerShell であろうと)CUI 環境のソフトを使うのは苦行でしかない(^^;;;

Qracle が提供している DB管理の GUI 環境「Oracle SQL Developer」は無償で使えるが、Oracle
アカウントを作る必要があり面倒くさいので(だって、この案件終わったら Oracle 案件はもう無い気がするし(笑))、みんな使ってるフリーの高機能 SQL クライアント「A5:SQL Mk-2」を使うことにした。

■ダウンロード&インストール

インストーラはないので、ダウンロードしてきたファイルを解凍して適当な場所に配置するだけ。

俺は Vector からダウンロードした。


a5m2_2.21.2_x64.zip がダウンロードされるので、それを解凍し、どこか適当なフォルダ(ディレクトリ)に置けば OK。


■接続情報の登録

A5M2.exe をダブルクリックして実行。
「データベース」→「データベースの追加と削除」で、「Oracle Database (OCI経由 or 直接接続)」を選択。

・接続方法 直接接続(Oracle Client不要)
・ホスト名 localhost
・サービス名 XEPDB1
・ユーザーID tester
・パスワード tester01

と指定して「テスト接続」を押し「接続に成功しました」となれば問題なし。「OK」押下で登録名を聞かれるのでわかりやすい名前を。ま、あとでリネームできるけど。
接続に成功しなかったら・・・何か typo しているので頑張って(笑)

20260701_A5_02.jpg

※ちなみに、このエントリーは A5:SQL Mk-2 の使い方を説明するものではないので、接続後にカレントスキーマを選んで TABLE を作成したりとかは自分で勉強してね。


■テーブルを作ってデータを登録

問題なく行えた。

20260701_A5_03.jpg

これで Spring Batch で DB 読込のテストができる。
勉強用に Oracle Database 21c Express Edition (XE) をインストールする。

■ダウンロード

 ↓

「Oracle Database 21c Express Edition for Windows (64-bit)」をクリックしてダウンロード開始。
(実際の業務では 19c を使うが、19c には Express Edition(XE) がない。あるのは 18c、21c だけ。19c スキップされている。19c の無償版のダウンロードは Oracle アカウントが必要だったり、色々面倒臭いので 21c(XE) で(笑))


■インストール

ダウンロードした OracleXE213_Win64.zip を解凍。

setup.exe と Oracle Database 21c Express Edition.msi があって悩むが、setup.exe 実行でいいよな?setup.exe ダブルクリックで実行。

けっこう時間がかかる。
ディフォルトの設定を変更することなく「次へ」「次へ」と進んでいったので、途中の画面画像は省略。

データベースパスワードは test@pass01 にする。(途中で @ マークを使っていることが後ほど面倒臭いことになるのをまだ俺は知らなかった(^^;)

20260701_oracle04.jpg

インストール完了。


■データベースへの接続

PS C:\Users\TESTER> sqlplus

SQL*Plus: Release 21.0.0.0.0 - Production on 水 7月 1 10:35:14 2026
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

ユーザー名を入力してください: system
パスワードを入力してください: test@pass01@localhost:1521/XEPDB1<実際は表示されない>
ERROR: ORA-12154: TNS: 指定された接続識別子を解決できませんでした

パスワードに @ マークを含む場合は、パスワードをダブルクォーテーションで囲ってやる必要がある。
@ なんか使わなきゃよかった。面倒くせえ(^^;

ユーザー名を入力してください: system
パスワードを入力してください: "test@pass01"@localhost:1521/XEPDB1<実際は表示されない>
最終正常ログイン時間: 水 7月  01 2026 10:16:04 +09:00


Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL>

無事接続されたので、test 用の表領域(テーブルスペース)を作成しよう。


■スキーマの作成

SQL> CREATE TABLESPACE test_space
  2   DATAFILE 'C:\app\data\test.dbf' SIZE 100M
  3   AUTOEXTEND ON NEXT 500K MAXSIZE 1024M;
CREATE TABLESPACE test_space
*
行1でエラーが発生しました。:
ORA-01119: データベース・ファイル'C:\app\data\test.dbf'の作成中にエラーが発生しました。
ORA-27040: ファイルの作成エラー、ファイルを作成できません
OSD-04002: ?t?@?C????[?v??????????S-Error: (OS 3)
?w?????p?X?????????????

あれ?失敗する。権限の問題?


■(ちょっと小休止)特殊な文字の入ってるパスワードは面倒なのでやめる

まだ、TABLESPACE  の作成が終わってないけど、その前に system ユーザのパスワードに @ マークが入っているので、うまく sqlplus で DB 接続できない。

Gemini に「ダブルクォーテーションでパスワードを囲まなきゃ」と言われたんだが、

sqlplus system/\"test@pass01\"@localhost:1521/XEPDB1
qlplus system/"test@pass01"@localhost:1521/XEPDB1

どちらも

ERROR: ORA-12154: TNS: 指定された接続識別子を解決できませんでした

になっちゃうなぁ(実際はダブルクォーテーションではなくシングルクォーテーションで囲まないとダメだったことが後ほどわかるんだけど(^^;;;)

ああ、面倒くせえ。@ マーク入りのパスワードは修正したほうがよさそうだ。

というわけで、system ユーザのパスワード変更。

ローカル(同一サーバー)での OS 認証で接続し、パスワード変更の QUERY を実行する。

PS C:\Users\TESTER> sqlplus / as sysdba

SQL*Plus: Release 21.0.0.0.0 - Production on 水 7月 1 11:23:38 2026
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.



Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL> ALTER USER SYSTEM IDENTIFIED BY testpass01;

ユーザーが変更されました。

SQL> ALTER USER SYS IDENTIFIED BY testpass01;

ユーザーが変更されました。

SQL>


パスワードは問題なく変更された様子。
別の Termnal を開いて、試しに接続してみるか。

PS C:\Users\TESTER> sqlplus system/testpass01@localhost:1521/XEPDB1

SQL*Plus: Release 21.0.0.0.0 - Production on 水 7月 1 11:29:13 2026
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

最終正常ログイン時間: 水 7月  01 2026 10:40:00 +09:00


Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL>

行けた・・・やっぱり、パスワードに @ なんか使うもんじゃないね(笑)


■スキーマの作成(再び)

SQL> CREATE TABLESPACE test_space
  2   DATAFILE 'C:\app\data\test.dbf' SIZE 100M
  3   AUTOEXTEND ON NEXT 500K MAXSIZE 1024M;
CREATE TABLESPACE test_space
*
行1でエラーが発生しました。:
ORA-01119: データベース・ファイル'C:\app\data\test.dbf'の作成中にエラーが発生しました。
ORA-27040: ファイルの作成エラー、ファイルを作成できません
OSD-04002: ?t?@?C????[?v??????????S-Error: (OS 3)
?w?????p?X?????????????

ダメか。

あっ、もしかしてディレクトリは先に作成しておかないといけないの?C:\app\data ディレクトリを作って再び CREATE TABLESPACE を実行。

SQL> CREATE TABLESPACE test_space
  2   DATAFILE 'C:\app\data\test.dbf' SIZE 100M><\span>
  3   AUTOEXTEND ON NEXT 500K MAXSIZE 1024M;

表領域が作成されました。

20260701_oracle09.jpg

テーブルスペースはできた。(しかし、エラーメッセージの文字化け化けなんなんかね?すごいことが起きてると思って、単純にディレクトリを手動で作っておかないといけないだけってところに思考がいかなかったよ(^^;;;)

続けてユーザ作成。(データベースの作成もできる DBA 権限を付与)

SQL> CREATE USER tester
  2   IDENTIFIED BY tester01
  3   DEFAULT TABLESPACE test_space
  4   TEMPORARY TABLESPACE TEMP
  5   PROFILE DEFAULT;

ユーザーが作成されました。

SQL> GRANT DBA TO tester;

権限付与が成功しました。


ばっちり。
これで初期インストール作業は終了。
Microsoft SQL Server の FLOOR 関数の動きが変。

例えば、DBに「返金 20,244,233円」という情報があり、これは返金なのでマイナス金額にした上で、返金額の税抜金額を計算する処理がある。
「返金 1,100円」なら -1.100円にした上で 1.1 で割って税抜 -1,000円を算出。返金 -1,100円からこの -1,000円を引いて -100円が消費税・・・のような計算をしている。
この際、端数は「0円からマイナス方向へ遠い値で切り捨てる(切り下げ)」ことになっている。「返金 126円」なら -126 / 1.1 で -114.54545 だから -115 となる。税抜が -115円で、消費税が -11円である。

ちなみに、この計算方法の是非についてはこの場で議論はしない。こういうルールで動いているのだからそれでいいのだ。

で、切り下げをする関数 FLOOR の動きがなんか変。

「返金 20,244,233円」の場合、

SELECT FLOOR(20244233 * -1 / 1.1) AS R

という SQL で R に -18,403,848.18 を切り下げた -18,403,849 が返ってきて、税抜 -18,403,849 で消費税 -1,840,384 となってほしい。

ところが、上記の SQL の結果は、R が -18,403,830 となる。19円も値がずれている。
しかし、元の数値をマイナスにするタイミング(-1 をかける)を変えるだけで、正しい数値が戻ってくる。

SELECT FLOOR(20244233 / 1.1 * -1) AS R 

だと、R列は -18,403,849 になる。
FLOOR に食わせる数値は()内で計算しているので、-1 するタイミングが前後しても関係ないと思うんだが・・・

ちなみにこれ、数字が大きい分だけ誤差も大きくなる。-1,000,000なら 1円ずれるが、-10,000,000 なら 10円ずれる。

使えねえなあ、FLOOR 関数。内部的に桁落ちしちゃってる???

ネット上を探してみたけど、「これこれこういう理由でずれる」という説明は見つけることができなかった。
「こういう使い方をしたらずれますよ」って情報は、メーカーとしてちゃんと提示しておくべきではないんかいな、マイクロソフトさんよお(^^;

Tedious ドライバーを使って SQL Server に接続できない・・・」というエントリーに書いたように、Tedious ドライバーを使って JavaScript(node.js)からの SQL Server 2019 へのアクセスだけがうまくいかない。

C# で試しにコンソールプログラム作ってアクセスしてみたけど、やっぱりうまくいくなあ。

Program.cs はこんな感じ。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

dbaccess();

        static void dbaccess()
        {
            string dataSource, initCatalog, userId, passWord, connectionString;
            dataSource = "DBSERVER\\MSSQL2019";
            initCatalog = "InazumaDB";
            userId = "sa";
            passWord = "hogepass";
            connectionString = @"Data Source=" + dataSource + ";Initial Catalog=" + initCatalog + ";User ID=" + userId + ";Password=" + passWord;
            string query_s = "SELECT TOMO_ID, TOMO_NAME, TOMO_MEMO FROM InazumaDB.dbo.M_TOMODACHI";

            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                //接続
                conn.Open();

                //SQL文を作成
                SqlCommand command_s = new SqlCommand(query_s, conn);

                using (SqlDataReader reader = command_s.ExecuteReader())
                {
                    //繰り返し読み込み
                    while (reader.Read())
                    {
                        //1~3列目の値を表示
                        Console.WriteLine(String.Format("{0}, {1}, {2}", reader[0], reader[1], reader[2]));
                    }
                }
                conn.Close();
            }
        }

これを実行すれば、コンソールに、

      1, アンモニア治郎, おごってくれるから友達
      2, クロム陽子, かわいいから友達
     14, ばいじん太郎, 事業に失敗したからそろそろ切ろう

こういう結果が表示される。

やっぱり、Tedious ドライバーが古くて SQL Server 2019 に対応していないってオチなんかね?

しばらく別件で忙しいので、調べている時間がないが・・・

今更だが、初めて知った。

Oracle で、DB(データベース)サーバの持っている日時だけ取得する場合、

SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') AS dt FROM DUAL;

とかすると、dt という項目に、例えば 2023/04/06 10:31:46 という値(現在日時)がセットされて返ってくる。

プログラマじゃない人に説明すると、SELECT 文は DB 上のテーブル(データが書き込まれている表)から値を取得する命令で、FROM のあとにテーブル名を指定する。
例えば、「個人情報」というテーブルに皆の名前や住所、年齢などが記録されているとして、その中から名前と年齢を取得しようとすると、

SELECT 名前, 年齢 FROM 個人情報

とすれば名前と年齢の一覧が取得できる。

しかし、上に書いたように、その DB サーバ自体が持っている日付(システム日付)を取得したいときなどは、なにかのテーブルにその値が記録されているというものではないので(「今何時?」って聞かれて、あなたは手帳を開いて今の時間を確認するかい?」ってことだね)、テーブル名を指定するわけにはいかない。でも、SELECT 文はテーブルを読む命令だから、なんかテーブルを指定してもらわないと・・・というのが Oracle の考えなわけで、仕方ないから「じゃあ、なんかダミーのテーブルを指定しますわ」ってものが DUAL なんですな。ダミーテーブルね。

で、さっき、SQL Server 触ってて、「DBサーバのシステム時間取りたいけど、ダミーテーブル名ってなんだっけ?」としばし悩んだのである。「DUAL」じゃ「オブジェクト名 'DUAL' が無効です。」って怒られるし。

そんで、ググったら、SQL Server にはダミーテーブルなんて概念ないので、From を省略すればいいだけと。

SELECT SYSDATETIME() AS dt

で、dt という項目に 2023-04-06 16:54:39.9673299 って値がセットされるって・・・

MySQL や PostgreSQL も一緒で、(ただし、SYSDATETIME という組み込み関数ではなく)

SELECT NOW() AS dt

のように指定する。

「そうなんかあ・・・初めて知った。SELECT 文に FROM がないのは気持ち悪いな」・・・と、Oracle 世代(DBと言えば Oracle だったおっさん世代)として素直に思ったが、さっき、PostgreSQL を DBMS とした自分の過去のプログラムを見たら、普通に「SELECT NOW() AS サーバ日時」とか書いてて、「初めて知ったわけではなく、完全に忘れていたのか」と加齢の恐ろしさに愕然としている(^^;;;

32bit 版の ODBC ドライバー経由で DB に接続する Access アプリを仕事で使わないといけないんだけど、メインのノートパソコンの Office は当然 64bit 環境なので、Access でデータソースの新規作成をしようとしても 32bit 版の ODBC ライバーが一覧に出てこない。

64bit 版Access で 32bit 版ODBCドライバーって使えないのかぁ~。上位互換で可能なのかと思っていた・・・

というわけで、新しい MS-Office 買ってきて、32bit版を新規インストール。

DVD版を買ったので、ドライブに DVD を突っ込むと「Setup.exeを実行するか?」と聞かれたので Yes とすると、いきなりインストールが実行された。64bit版の・・・

途中で 64bit/32bit のどっち?って聞かれるのかと思ってたわ・・・
そういえば昔の話だが、Office って 64bit版の開発が遅れてて、64bit の Windows OS にインストールするときも、勝手に 32bit版が選ばれるので、あとでもう一度 64bit版を入れ直したりってことがあったな(^^; 今は勝手に 64bit版が選ばれるのね(笑)

インストールを途中で止めると中途半端にファイルが残ったりしそうなので、最後までインストールしてからアンインストール。改めて、Setup32.exeを実行し 32bit版 Office をインストールした。

で、無事 32bit版 ODBC ドライバーが使えることを確認。 

でも、よく調べたらこの DB、64bit版の ODBC ドライバーもリリースしてるんで、それ使えばいいんじゃない?とも思ったのだが、アプリのメーカーの動作保証対象が 32bit版なので仕方ないのである・・・(^^;
プログラム内で、仮テーブル上のデータをまるごと本テーブルにINSERTする処理があって、特になんの編集もなく突っ込むだけだから、

SELECT * INTO hon_tbl FROM kari_tbl

みたいな SQL を書いてたわけよ。(DBMS は SQL Server です)

そしたら、(もちろんこのSQL以外にもいくつかのフラグの更新SQLなどが流れているのでトランザクション処理をしてるんだけど)Roolback のときも Commit のときも、

System.InvalidOperationException: 'この SqlTransaction は完了しています。再度使用することはできません。'

という例外が発生する。
SELECT INTO すると、勝手に Commit されちゃうの???謎~

「SELECT INTO するのならトランザクション処理は必要なかろう」という乱暴な意見もありそうだが、いやいや、やっぱおかしいやろう。

トランザクション処理はなるべく範囲を小さく・・・は基本だが、いくつかのテーブルを更新してから Commit なんて普通のことで、いくらなんでも SELECT INTO したからトランザクション終わり!ってもんではない。

結局、1件ずつ INSERT 文を発行する形に直したが、なんか納得いかんなあ

そういうもんなの???>SQL Server に詳しい人!

<追記>
すぐに SNS で偉い人が「SELECT INTO は SQL ではなく DDL 扱いじゃないか?INSERT INTO SELECT ならトランザクション内として処理されるはず」とアドバイスをくださった。
なるほど~。日頃、SQL と DDL の違いを意識することのない適当エンジニアです。すみません(^^; 勉強になります!
他人が作った SQL Server を使う VB.NET のソースを修正していたら、

SELECT TOP 0 * INTO new_hoge FROM org_hoge 

みたいな SQL を発行してるんで、「0行だけ取ってきて新しいテーブルにインサートって何?」って思ったら、これ、定義だけコピって新しいテーブルを作る方法なんじゃね。

へえ、SQL Server じゃこんなことできるんだ・・・と思って、PostgreSQL で同じように、

SELECT * INTO new_hoge FROM org_hoge LIMIT 0 OFFSET 0

ってやってみたら、org_hoge の定義で新しい空のテーブル new_hoge が作られた。

「へえ」と。俺は職業プログラマなので、他のテーブルと同じ定義で空のテーブルを作るときも、ちゃんと CREATE TABLE 文を書いて作ってた。どっちみち、設計資料として必要だしね。それに、たまたまこの長い人生の中で、プログラム内で(例えばワークテーブルを作るとか?)こういうことをする機会も無かったので、こんな簡単な方法知らなかったよ(笑)
知っている人にとっては「なんだ、そんな簡単なこと!」なんだろうけど(笑)

で、MySQL でも、

SELECT * INTO new_hoge FROM org_hoge LIMIT 0,0

とやってみたら、これは

ERROR 1327 (42000): Undeclared variable: new_hoge

とエラーになった。new_hoge は宣言されてねえぞ・・・って?

調べてみると、MySQL では SELECT * INTO TABLE <新しいテーブル>・・・という書き方はサポートされていなかった。マニュアルには、

INSERT INTO new_hoge SELECT * FROM org_hoge LIMIT 0,0

にしろ・・・と書いてあるらしいが、そもそも MySQL にはこういう方法での CREATE TABLE 機能は無いそうで、この場合も「new_hoge なんてテーブルは無ぇよ!」と怒られるらしい。

結局、MySQL では「SELECT した情報で空のテーブルを新しく作る」ということはできないようだ。

素直に、

CREATE TABLE new_hoge LIKE org_hoge

でテーブルを作りなさいということだね。

他の DBMS ではどうなのかは面倒くさいので調べていない(笑)

SQL Server のストアド・プロシージャは、SQL Server Management Studio で修正することはあったんだけど、新規に作ったことはなかった。
(メンテナンスし辛いので(DB内のすべてのストアド・プロシージャに対するワード検索とか、いちいち SQL 書かないといけないし)、できるだけ使いたくない(笑))

修正のときは、ソースを直して「実行」するだけだったので、(今回は、もともと存在するストアドの内容をコピーして、色々修正を加えた上で新規登録する)同じように最後に「実行」すると、

メッセージ 208、レベル 16、状態 6、プロシージャ p_data_create、行 64 [バッチ開始行 7]
オブジェクト名 'p_data_create' が無効です。

というエラーが出る。

これは、

ALTER PROCEDURE [dbo].[p_data_create]

になっていたため。
ALTER は 「変更する/改める」という意味だから、変更対象のストアドが見つからないってエラーが出てた。

新規作成時は

CREATE PROCEDURE [dbo].[p_data_create]

になってないとね。DB や TABLE を作るときと一緒だから。

ソースコピーしてきて、とりあえずプロシージャ名だけ一括変更して登録しようとしたのが敗因だった(^^; ちゃんとソースは読みましょう(笑)

登録後は CREATE を ALTER に変更しておく。
Microsoft Access で、「クエリデザイン」→「SQL ビュー」として直接以下のような SQL を叩くと、

SELECT 
    Format(Uri_day,'mm/dd') As Uri_day,
    Denpyo_no
FROM 
    T_Uriage 
WHERE 
    Denpyo_no = '001002'

なんか、「クエリ定義の SELECT で指定されている別名 'Uri_day' が循環参照を発生させています。」とエラーになる。

20210309_access1.jpg

どうも、式(Format)の中で使っている列名(Uri_day)と同じ名前を、計算結果の別名には使えないようだ。別名を Uri_Uri_Day とかに変えたら上手くいった(笑)。

Excel でも同じようなエラーが出るケースがあるようなので、Microsoft べったりの開発者にとっては「常識」なのかな?
でも、つまりこれって、a = a + 1 とか、そういうことが出来ないっていうのと同じことじゃない?相当変な話やな(笑)

他の DBMS でもこんなことになるっけ?と思い、MySQL で似たようなことをやってみた。

mysql> SELECT
    ->     DATE_FORMAT(cdate,'%m/%d') AS cdate,
    ->     user_no
    -> FROM
    ->     t_user
    -> WHERE
    ->     user_no = 'AB129'
    -> ;
+-------+---------+
| cdate | user_no |
+-------+---------+
| 06/10 | AB129   |
+-------+---------+
1 row in set (0.01 sec)

ならんやん!!正常に実行された。

やっぱ、なんというか・・・Microsoft めぇ~な話やなあ(笑)。Microsoft の「常識」は社会の「非常識」(笑)

※ちなみに、VB.NET のプログラム内から同じ SQL で Access を参照してもエラーにはならない。

おいっ!Microsoft!!(^^;

※「循環参照」を「環境参照」って間違えてたことにさっき気づきました(^^; 単なる打ち間違いです。

このアーカイブについて

このページには、過去に書かれたブログ記事のうちデータベースカテゴリに属しているものが含まれています。

前のカテゴリはWindowsです。

次のカテゴリはパソコンです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら