質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

2228閲覧

NodeでのORACLEからのデータ取得

wolf2

総合スコア19

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/04/12 10:32

現在NodeでORACLEからデータを取得する処理を実装しようとしているのですが、
下記のコードを試してもexecute内では値が取れるのですがデータを持ちまわる事が
出来ません。どうすれば持ちまわれますか?

Node.js

1var oracledb = require("oracledb"); 2 3module.exports = { 4 Syain_Select: function (SYAIN_CD) { 5 let sql = "select * from SYAIN_TB"; 6 let res = ""; 7 8 oracledb.getConnection( 9 { 10 connectString: "IP", 11 user: "USER", 12 password: "PASS", 13 }, 14 function (err, conn) { 15 if (err) { 16 console.error(err.message); 17 return; 18 } 19 conn.execute(sql, function (err, results, req) { 20 res = results.rows[0]; 21 conn.close(); 22 }); 23 } 24 ); 25 console.log(res); 26 } 27};

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

データを持ちまわる事が出来ません。どうすれば持ちまわれますか?

基本的には出来ませんよ、
なので諦めてMr.ドリラーのように処理終了まで掘り続けてください。

でもまぁ、コールバック関数の使い方をしっかり覚えれば、
こんなに掘りまくらなくてもコールバック関数を要求する関数を上手く作ってハンドリング出来るので、Node.js力が身につけば自然と解決出来るでしょう。
Promiseやasync/awaitもその一環ですので、Node.jsを使い続けるならこれらの機能をちゃんと勉強して使いこなせるようにしてください。

これがベースです。


しかし、これが本筋じゃなさそうですね。
なのでちゃーんとデータを持ちまわる必殺技を覚える必要があるでしょう。
当然難解ですので、頑張って付いてきて下さいね。

代表的な手法は下記の2通りの組み合わせです。

  • 親スコープからオブジェクトや配列等を渡してやる
  • EventEmitterを覚える

このいずれか、または両方を組み合わせて実現させます。
EventEmitterは結構難解ですが、覚えなくても大丈夫です(理由は後述)

というわけで「親スコープからオブジェクトや配列等を渡してやる」を解説していきます。
まず、JavaScriptの変数の値はプリミティブ値オブジェクトかの二択です。
この内、オブジェクトはメモリ空間のアドレス値を使い、その実体はどこからでもアクセス出来るので、関数の引数や戻り値として別のものに手渡したとしても普通に中身にアクセスして読み書きが出来ます。

JavaScript

1const user = { 2 name: 'taro', 3 age: 18 4} 5const main = he => { 6 console.log(he.name) // taro 7 he.sex = 'male' 8 return he 9} 10const user2 = main(user) 11 12console.log(user) // {name: "taro", age: 18, sex: "male"} 13console.log(user2) // {name: "taro", age: 18, sex: "male"}

このように、userは引数としてmain関数の中に突っ込んだだけなのに、
内部の関数でheを変更した余波がそのまま反映されましたね。
これを利用して値を取り出す事が出来ます。

この時、userの中身が数値や文字列等のプリミティブ値の場合は絶対に実現出来ませんし、
オブジェクトを渡したとしても関数の中でhe = {}のように代入をした場合、メモリ空間上の参照アドレス値が吹っ飛んで値が取り出せなくなりますので、
he.hoge = 123等のように、必ず内部のキー情報にアクセスしながら代入するようにしてください。

では、質問文のコードを軸にoracleから値を吸い出すロジックを考えていきましょう。
元々のコードはちょっと手直ししてこんな感じですかね。

JavaScript

1// 仮にoracle.jsとする 2const oracledb = require("oracledb"); 3 4module.exports = { 5 // 引数にオブジェクトを要求する 6 Syain_Select: function (state) { 7 const {SYAIN_CD} = state; // 元々の引数予定だったSYAIN_CDはstate内へ引っ越し 8 let sql = "select * from SYAIN_TB"; 9 let res = ""; 10 11 oracledb.getConnection( 12 { 13 connectString: "IP", 14 user: "USER", 15 password: "PASS", 16 }, 17 function (err, conn) { 18 if (err) { 19 console.error(err.message); 20 return; 21 } 22 conn.execute(sql, function (err, results, req) { 23 res = results.rows[0]; 24 state.response = res; // ここでstateに保存! 25 conn.close(); 26 }); 27 } 28 ); 29 } 30};

続いて使う側です。

JavaScript

1const oracle = require('./oracle.js'); 2const state = {}; // 状態を意味するオブジェクトを宣言しておく 3 4state.SYAIN_CD = '123456'; // 検索に利用するはずだった社員コードがstate内に引っ越したのでここに格納 5 6oracle.Syain_Select(state); // 実行 7 8// JSは非同期処理を実行すると了解といってすぐ戻ってくるのでresultにはアクセス出来ない 9console.log(state); // {SYAIN_CD: '123456'} 10 11// なので待つ 12const wait = () => { 13 console.log(state); 14 if (state.result) return 15 setTimeout(wait, 3000); 16}

なんか微妙だなぁ…といった感じですが、この技法単体ではこんなもんです。
待てば結果が返って来て取得出来るだけなので御の字でしょう。
嫌ならコールバック関数で全部数珠つなぎにして頑張ってください。

次の章はEventEmitterと併用して使えない子からステップアップを目指します。


次にNode.jsを使って何を表現したいのでしょうか?
それによりアドバイスが変わります。

  • Expressを使ってWebサイトを構築したい
  • WebSocketを使ってWSサーバを構築したい

Node.jsを扱う動機で多いのは、このどちらかでしょう。
コイツらはEventEmitterの機能が搭載されているので、覚える必要がないと言ったのはそういう理由からです。
これらとは関係なく実現させたければ自分でEventEmitterを覚えて使いこなせるようにしてください。

今回はExpressとの併用を紹介しますので、WS目当てなら参考に頑張ってください。
まずは、サーバーを公開する前にDBにアクセスして置かなければならないモノを取得します。

JavaScript

1const require('oracle.js'); 2const state = {}; 3 4const express = require('express'); 5const app = express(); 6app.get('/', (req, res) => { 7 res.json(state.result); 8}) 9 10// Webサーバは80番ポートで待ち受けなければ誰もアクセス出来ないので、結果が取れるまでせき止める 11const wait = () => { 12 if (!state.result) { 13 return setTimeout(wait, 1000); 14 } 15 app.listener(80); 16 console.log('get ready'); 17}

これでget readyがコンソール上に表示されてからアクセスすれば、
httpアクセスすると社員情報が返ってきます。


いや、社員コードは動的にアクセスしたいんだが

しょうがない、やっぱりコールバック関数に関するあたりの説明も必要ですね…
今回はNoderらしい方法でやっていきます。

まず、OracleのコネクションはWebサーバが毎回切断するのはアホです。
張りっぱなしが当然です。
なので関数を分けて張りっぱなしに出来るようstateオブジェクト内に保存し続ける作りにします。

各関数の引数にコールバック関数という引数を用意して要求するようにします。
この時、他のコールバック関数を引数に取る関数は、全て最終引数が該当するのでそれに合わせます。

JavaScript

1// oracle2.js 2const oracledb = require("oracledb"); 3 4module.exports = { 5 getConn: function (cb) { 6 oracledb.getConnection({ 7 connectString: "IP", 8 user: "USER", 9 password: "PASS", 10 }, cb); 11 }, 12 Syain_Select: function (conn, SYAIN_CD, cb) { 13 // TODO: ここ入力値がそのままSQL文になってる可能性があるのでエスケープ作っておいてください 14 let sql = `select * from SYAIN_TB where SYAIN_CB = '${SYAIN_CB}'`; 15 conn.execute(sql, cb); 16 } 17};

こんな殺風景で大丈夫か?
これが最善です、結果を受け取った側が今後の動作を考えるべきなので、
こいつらがする事はシンプルな事にとどめましょう。

続いてExpressです。

JavaScript

1const oracle = require('./oracle2.js'); 2const state = {}; // いつものやつ 3 4const express = require('express'); 5const app = express(); 6app.get('/:code', (req, res) => { 7 const code = req.params.code 8 oracle.Syain_Select(state.conn, code, (err, results, req) => { 9 if (err) { 10 // 社員番号が取れなかったみたいな感じで 11 res.status(400).json(err.message); 12 return; 13 } 14 res.json(results.row); 15 }); 16}) 17 18oracle.getConn((err, conn) => { 19 if (err) throw err; // Oracleに接続出来なければサーバーは起動できない 20 state.conn = conn; // getConnから持ち帰ってきたconnを保存 21 app.listen(80); // サーバを起動 22 console.log('get ready.'); 23})

ちょっと知恵の輪みたいに複雑でしたが、Node.jsではこのような流れで必要な値を適宜外のスコープに持ち帰りながらサーバを構築する必要があります。
ゆっくり読み返しながら反芻していってください。

処理が増えると長い直列の非同期処理が必要な事もあるかと思います。
どんどんネストが深くなっていきコードがカオスになっていきます。
ファイルを区切って抽象化したり、Promiseやasync/awaitの構文を覚えて管理出来るように学習してください。

それでは良きNode.jsライフを

投稿2018/04/12 13:18

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Node.jsはノンブロッキングI/Oなので、非同期処理で取得した値を別の箇所で使用する場合はPromiseやasync/awaitを使いましょう。

Promise: https://qiita.com/toshihirock/items/e49b66f8685a8510bd76
async/await: https://qiita.com/Anders/items/dfcb48d8b27ceaffb443

投稿2018/04/12 10:37

k.tada

総合スコア1679

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

callbackのみでDB操作は現実的ではありません。
node-oracledbはPromise化されているのでPromiseでがんばります。
https://oracle.github.io/node-oracledb/doc/api.html#promiseoverview

Promiseならばasync/await構文にもすぐに書き直せます。
上記URLのサンプルはこんな感じで書けます。
エラー処理はPromise.catchやtry-catchで挙動を確認しながら勉強してみてください。
突破口となれば幸いです。

js

1const oracledb = require('oracledb'); 2 3(async ()=>{ 4 const conn = await oracledb.getConnection({ 5 user : "hr", 6 password : "welcome", 7 connectString : "localhost/XE" 8 }); 9 const result = await conn.execute( 10 `SELECT department_id, department_name 11 FROM departments 12 WHERE manager_id < :id`, 13 [110] // bind value for :id 14 ); 15 console.log(result); 16})()

投稿2018/04/13 09:13

so87

総合スコア764

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問