Visual StudioからのOracle PL/SQLのデバッグ

<このテキストを削除しないでください。これは、ブラウザ実行時に生成される"主要"なトピック一覧のプレースホルダです。>

目的

このチュートリアルでは、Visual StudioからOracle PL/SQLをデバッグする方法について説明します。

所要時間

約30分

概要

Oracle Developer Toolsに統合されたPL/SQLデバッガを使用すると、Visual Studioを終了せずに、.NETおよびOracleソリューションのエンド・ツー・エンド・デバッグを行うことができます。 プロシージャとファンクション(スタンドアロンおよびパッケージ済みの両方)、オブジェクト・メソッド、およびトリガーなどのPL/SQLコードを、Visual Studio環境内からC#またはVB.NETコードをデバッグする場合と同じ方法でデバッグできます。 Oracle Developer Toolsに統合されたPL/SQLデバッガでは、ブレーク・ポイントの設定、変数値の表示と変更、および呼出し履歴の検査などの従来のデバッグ機能を使用できます。

PL/SQLデバッガは、次の3つのモードのいずれかで使用します。

ダイレクト・データベース・デバッグ
外部アプリケーション・デバッグ
多層アプリケーション・デバッグ .NETアプリケーションの開発時におけるもっとも強力なオプションは、多層アプリケーション・デバッグ・モードです。 このモードでは、Visual Studioソリューション内から.NETコードおよびPL/SQLコードの両方をシームレスにデバッグできます。 .NETコードから直接PL/SQLコードに移動して、再び戻ることができます。

このチュートリアルでは、多層アプリケーション・デバッグ・モードを使用します。 このモードでは、開発者は、デバッグ・セッション中に.NETコードとPL/SQLコードを同時に操作できます。

 

前提条件

このチュートリアルを始める前に以下のことを確認してください。

.

Microsoft Visual Studio 2010をインストールしていること。

.

Oracle Database 9.2以上またはOracle Database XEをインストールしていること。

.

Oracle 11g Oracle Data Access Components with Oracle Developer Tools for Visual Studioバージョン11.2.0.1.2以上を、OTNから入手し、インストールしていること。

.

これらのファイルを作業ディレクトリに解凍していること。

Oracle接続の作成

アプリケーションの作成を開始する前に、Visual Studioを開いて接続を作成します。 以下の手順を実行します。

.

Visual Studioを開きます。

.

View」→「Server Explorer」を選択します。

 

.

Data Connections」を右クリックして、「Add Connection...」を選択します。

 

.

Add Connectionダイアログ・ボックスで、適切なデータソース・プロバイダを選択します。

注: Data sourceが、Oracle Database(Oracle ODP.NET)にすでに設定されている場合は次の手順に移動するか、「Change」をクリックして、データソースおよびデータ・プロバイダを選択します。

Change Data Sourceダイアログ・ボックスで、Data sourceとして「Oracle Database」を選択し、Data providerとして「Oracle Data Provider for .NET」を選択します。 「OK」をクリックします。

 

.

Data source nameドロップダウンで、使用しているOracle Databaseインスタンスの<SID>を選択します。 User nameとPasswordにHRと入力し、「Save password」をクリックして「Test Connection」をクリックします。

 

.

テスト接続が成功しました。 「OK」をクリックします。

 

.

OK」をクリックします。

 

.

HR接続が作成されました。 同様に、SYS接続も作成する必要があります。 「Data Connections」を右クリックして、「Add Connection...」を選択します。

 

.

Data sourceはOracle Database(Oracle ODP.NET)に設定されている必要があります。 Data source nameドロップダウンで、使用しているOracle Databaseインスタンスの<SID>を選択します。

User nameにSYSと入力し、使用しているパスワードを入力して、「Save password」をクリックし、Roleとして「SYSDBA」を選択して「Test Connection」をクリックします。

 

.

テスト接続が成功しました。 「OK」をクリックします。

 

.

OK」をクリックします。

 

.

SYS接続が作成されました。 HR.ORCLとSYS.ORCLの両方を開いて、接続を作成します。

 

デバッグ権限の付与

デバッガを使用するには、debug connect session権限およびdebug any procedure権限をHRユーザーに付与する必要があります。 以下の手順を実行します。

.

Server Explorerパネルで、「SYS.ORCL」接続を右クリックして、「Query Window」を選択します。

 

.

次のコマンドを入力して、「Execute」をクリックします。

GRANT debug any procedure, debug connect session TO hr;

注:Oracle Database Release 9.2を使用している場合は、grant debug any procedure to hr;を実行する必要があります。

 

.

文が正常に実行されました。

 

PL/SQLパッケージとパッケージ本体の作成

このトピックでは、PL/SQLパッケージと、PL/SQL配列内の各数値が素数であるかどうかを判定するパッケージ本体を作成し、次にPL/SQLレコードを使用してJOBS表に新しい行を作成します。 以下の手順を実行します。

.

Server Explorerパネルで、「HR.ORCL」を右クリックして、「Query Window」を選択します。

 

.

作業ディレクトリにダウンロードしたファイルのうちのPLSQL_Debug_Package.txtファイルからコードをコピーし、Queryウィンドウに貼り付けて「Execute」をクリックします。

CREATE OR REPLACE PACKAGE "HR"."OBE" IS
-- types for associative arrays that client will pass as arguments
TYPE "T_IN_VALUES" IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
TYPE "T_OUT_VALUES" IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

-- procedure that accepts two associative arrays
-- determines if an element is likely prime and
-- sets value in output array
PROCEDURE "DETERMINE_PRIMES" ("P_IN_VALUES" IN T_IN_VALUES,
"P_OUT_VALUES" OUT T_OUT_VALUES);

-- function that determines if a number is likely prime
FUNCTION "IS_PRIME" ("P_NUMBER" IN NUMBER) RETURN NUMBER;

-- constants used to return values from function
IS_NOT_A_PRIME CONSTANT NUMBER DEFAULT 0;
IS_A_PRIME CONSTANT NUMBER DEFAULT 1;

-- pl/sql record type for the jobs table
"JOBS_REC" jobs%rowtype;

-- pl/sql procedure to add new job to jobs table
PROCEDURE "ADD_NEW_JOB" ("P_JOB_ID" IN JOBS.JOB_ID%TYPE,
"P_JOB_TITLE" IN JOBS.JOB_TITLE%TYPE,
"P_MIN_SALARY" IN JOBS.MIN_SALARY%TYPE,
"P_MAX_SALARY" IN JOBS.MAX_SALARY%TYPE);

END "OBE";

.

PL/SQLパッケージが正常に実行されました。

 

.

作業ディレクトリにダウンロードしたファイルのうちのPLSQL_Debug_Packagebody.txtファイルからコードをコピーし、Queryウィンドウに貼り付けて「Execute」をクリックします。

CREATE OR REPLACE PACKAGE BODY "HR"."OBE" IS
-- procedure that processes the incoming associative arrays
-- calls the method IS_PRIME to determine if element is likely prime
PROCEDURE "DETERMINE_PRIMES" ("P_IN_VALUES" IN T_IN_VALUES,
"P_OUT_VALUES" OUT T_OUT_VALUES) IS
BEGIN
-- loop through each element in the incoming array
-- and set the value for the corresponding element
-- in the out array
for i in p_in_values.first..p_in_values.last
loop
p_out_values(i) := is_prime(p_in_values(i));
end loop;
END "DETERMINE_PRIMES";
-- private function to determine if a number is likely prime
FUNCTION "IS_PRIME" ("P_NUMBER" IN NUMBER) RETURN NUMBER IS
l_sqrt number := 0;
l_sqrt_ceil number := 0;
l_divisor number := 0;
l_divisor_squared number := 0;
begin
-- prime numbers must be >= 2
if p_number < 2 then
return IS_NOT_A_PRIME;
end if;
-- only integers can be prime
if p_number != ceil(p_number) then
return IS_NOT_A_PRIME;
end if;
-- 2 is the only even prime, so it is a special case
if p_number = 2 then
return IS_A_PRIME;
end if;
-- eliminate all other even numbers
if mod(p_number,2) = 0 then
return IS_NOT_A_PRIME;
end if;
-- if the sqrt of the number is an integer, the number is not prime
l_sqrt := sqrt(p_number);
l_sqrt_ceil := ceil(l_sqrt);
if l_sqrt = l_sqrt_ceil then
return IS_NOT_A_PRIME;
end if;
-- the number has passed the basic elimination tests and may be prime
-- loop through set of odd divisors to determine if number is prime
l_divisor := 3;
for i in 1..l_sqrt_ceil
loop
l_divisor_squared := l_divisor * l_divisor;
-- if l_divisor is a factor of p_number, then not a prime
if mod(p_number,l_divisor) = 0 and l_divisor_squared < p_number then
return IS_NOT_A_PRIME;
end if;
-- no factor found, therefore number is likely a prime
if l_divisor_squared > p_number then
return IS_A_PRIME;
end if;
l_divisor := l_divisor + 2;
end loop;
END "IS_PRIME";
-- pl/sql procedure to add new job to jobs table
PROCEDURE "ADD_NEW_JOB" ("P_JOB_ID" IN JOBS.JOB_ID%TYPE,
"P_JOB_TITLE" IN JOBS.JOB_TITLE%TYPE,
"P_MIN_SALARY" IN JOBS.MIN_SALARY%TYPE,
"P_MAX_SALARY" IN JOBS.MAX_SALARY%TYPE) IS
BEGIN
-- use the package variable JOBS_REC to create new record
jobs_rec.job_id := p_job_id;
jobs_rec.job_title := p_job_title;
jobs_rec.min_salary := p_min_salary;
jobs_rec.max_salary := p_max_salary;
-- insert the job record into the table
insert into jobs (job_id, job_title, min_salary, max_salary)
values (jobs_rec.job_id, jobs_rec.job_title,
jobs_rec.min_salary, jobs_rec.max_salary);
END "ADD_NEW_JOB";
END "OBE";

 

 

.

PL/SQLパッケージ本体が正常に実行されました。

 

.

Server ExplorerのHR.ORCL接続で、「Packages」→「OBE」を開いて、作成されたオブジェクトの一覧を確認します。

 

.

OBE」パッケージを右クリックして、「Compile Debug」を選択します。 このアクションで、パッケージのデバッグが有効になります。

 

.

パッケージが正常にコンパイルされました。 Outputウィンドウを閉じます。 次に、「Start Page」タブをクリックします。

 

Visual Studioのプロジェクトの作成

新しいプロジェクトを作成する準備ができました。 以下の手順を実行します。

.

Fileメニューから「New」→「Project」を選択します。

 

.

Project Typesで「Visual C# : Windows」を選択し、Templatesで「Console Application」を選択します。Nameにplsqldebugobe1と入力し、Locationフィールドにファイルを保存するディレクトリを入力します(注:ディレクトリが存在しない場合は、作成されます)。「OK」をクリックします。

 

.

プロジェクトが作成されました。 これで、参照を追加できます。

 

.

Project」→「Add Reference...」を選択します。

 

.

参照のリストを下方向にスクロールし、「Oracle.DataAccess」を選択して「OK」をクリックします。

 

.

作業ディレクトリにダウンロードしたファイルのうちのPLSQL_Debug_csharpcode.txtファイルからコードをコピーし、Visual Studio のProgram.csウィンドウに貼り付けます。 「Program.cs」タブを右クリックして、「Save Program.cs」を選択します。

using System;
using System.Data;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
namespace plsqldebugobe1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// constants used to represent values returned
// from the pl/sql procedure call
const int IS_NOT_A_PRIME = 0;
const int IS_A_PRIME = 1;
// display progress message
Console.WriteLine("Testing array for prime numbers...\n");
// connection string: adjust for your environment
string constr = "User Id=hr; Password=hr; Data Source=ORCL; enlist=false; pooling=false";
// create and open connection object
OracleConnection con = new OracleConnection(constr);
con.Open();
// create command object for the function call
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandText = "OBE.determine_primes";
// set the proper command type
cmd.CommandType = CommandType.StoredProcedure;
// parameter object for the input array
OracleParameter p_in_values = new OracleParameter();
p_in_values.OracleDbType = OracleDbType.Decimal;
p_in_values.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_in_values.Value = new decimal[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
p_in_values.Size = 10;
p_in_values.Direction = ParameterDirection.Input;
// parameter object for the output array
OracleParameter p_out_values = new OracleParameter();
p_out_values.OracleDbType = OracleDbType.Decimal;
p_out_values.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_out_values.Value = null;
p_out_values.Size = 10;
p_out_values.Direction = ParameterDirection.Output;
// add parameters to the collection
// they must be added in the proper
// order when using bind by position (the default)
cmd.Parameters.Add(p_in_values);
cmd.Parameters.Add(p_out_values);
// execute the pl/sql procedure to populate output array
cmd.ExecuteNonQuery();
// display results to console window
for (int i = 0; i < p_in_values.Size; i++)
{
foreach (OracleParameter p in cmd.Parameters)
{
// the input array is treated as System.Decimal[]
// within the .NET code
if (p.Value is System.Decimal[])
{
Console.Write("The Number {0} ", ((p.Value as System.Decimal[])[i]).ToString());
}
// the output array is treated as OracleDecimal[]
// within the .NET code
if (p.Value is OracleDecimal[])
{
if (((p.Value as OracleDecimal[])[i]).ToInt32() == IS_NOT_A_PRIME)
{
Console.WriteLine("is not a prime number!");
}
else if (((p.Value as OracleDecimal[])[i]).ToInt32() == IS_A_PRIME)
{
Console.WriteLine("is a prime number!");
}
}
}
}
// display a separator line
Console.WriteLine();
// display progress message
Console.WriteLine("Using PL/SQL record...\n");
// remove parameters from command collection
// and set new command text
cmd.Parameters.Clear();
cmd.CommandText = "
obe.add_new_job";
// parameter object for the job_id
OracleParameter p_job_id = new OracleParameter();
p_job_id.Value = "IT_DBA";
// parameter object for the job_title
OracleParameter p_job_title = new OracleParameter();
p_job_title.Value = "Database Administrator";
// parameter object for the min_salary
OracleParameter p_min_salary = new OracleParameter();
p_min_salary.OracleDbType = OracleDbType.Decimal;
p_min_salary.Value = 10000;
// parameter object for the max_salary
OracleParameter p_max_salary = new OracleParameter();
p_max_salary.OracleDbType = OracleDbType.Decimal;
p_max_salary.Value = 15000;
// add parameters to collection
cmd.Parameters.Add(p_job_id);
cmd.Parameters.Add(p_job_title);
cmd.Parameters.Add(p_min_salary);
cmd.Parameters.Add(p_max_salary);
// execute the pl/sql procedure to add new job
cmd.ExecuteNonQuery();
// display simple message to indicate procedure completed
Console.WriteLine("New job successfully created!");
// display a separator line
Console.WriteLine();
// Simple prompt to prevent the console from closing
// when running from the IDE
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
// clean up objects
p_max_salary.Dispose();
p_min_salary.Dispose();
p_job_title.Dispose();
p_job_id.Dispose();
p_out_values.Dispose();
p_in_values.Dispose();
cmd.Dispose();
con.Dispose();
}
}
}

 

デバッグ環境の設定

デバッグ環境を使用するには、事前にいくつかのプロパティとオプションを設定する必要があります。 以下の手順を実行します。

.

Project」→「plsqldebugobe1 Properties...」を選択します。

 

.

Debug」を選択します。

 

.

Enable the Visual Studio hosting process」の選択を解除し、「plsqldebugobe1」タブを右クリックして「Save Selected Items」を選択します。

 

.

Tools」→「Options...」を選択します。

 

.

Show all settings」チェック・ボックスにチェックを入れます。 注: このチェック・ボックスが表示されない場合、すでにこのチェック・ボックスが選択されていることを意味します。

下方向にスクロールして、「Oracle Developer Tools」を開きます。 「PL/SQL Debugging」を選択します。 使用可能なデータベース接続で、「HR.ORCL」接続のチェック・ボックスをチェックします。 IPアドレスのドロップダウン・ボックスとTCP/IPポートの範囲が表示されることを確認してください。 PL/SQLのデバッグ中、Oracle Databaseは、IPアドレスとこの範囲にある任意のポートを使用してTCP/IP経由でVisual Studioに接続します。 使用するマシンに複数のIPアドレスが割り当てられている場合、Oracleデータベースから接続できるアドレスを選択するよう注意してください。 また、指定したポート範囲が、使用しているマシン上で開いているポートであること、およびファイアウォールでブロックされていないことを確認してください。

 

.

Tools」→「Oracle Application Debugging」を選択します。

再度、「Tools」メニューを選択すると、メニュー項目の前にチェック・マークが表示されます。

ブレーク・ポイントの設定

このトピックでは、実行中にデバッガを停止するために、C#コードとPL/SQLコードの両方にブレーク・ポイントを設定します。 以下の手順を実行します。

.

Program.cs」タブをクリックして、cmd.ExecuteNonQuery()文を見つけます。

 

.

Program.csコードのcmd.Parameters.Add(p_out_values)文にブレーク・ポイントを作成します。 行の任意の場所をクリックし、右クリックして「Breakpoint」を選択します。次に、「Insert Breakpoint」を選択します。 あるいは、ブレーク・ポイントを設定する場所でコード・ウィンドウの一番左端にある灰色部分をクリックすることもできます。

 

.

ブレーク・ポイント・インジケータが表示されます。

 

.

パッケージを実行後、別のブレーク・ポイントを作成します。

 

 

.

Server Explorerで、「DETERMINE_PRIMES」をダブルクリックしてコードを開きます。

 

.

DETERMINE_PRIMESプロシージャで、BEGIN文の後の最初の文にブレーク・ポイントを作成します。

 

.

プロシージャの一覧から「ADD_NEW_JOB」を選択します。

 

.

BEGIN文の後の最初の文にブレーク・ポイントを作成します。

 

.

Program.cs」タブをクリックします。

PL/SQLのデバッグ

このトピックでは、デバッガを使用してプログラムを実行します。 以下の手順を実行します。

.

プログラムをデバッグする準備はできています。 「Debug」→「Start Debugging」を選択します。

 

.

デバッガが最初のブレーク・ポイントで停止します。 変数とそれぞれの値を確認するには、ウィンドウの下部にある「Locals」タブをクリックします。 このブレーク・ポイントまでのコードを確認して、配列バインド・パラメータがどのように設定されているかを理解します。

 

.

次の行に移動するには、「Step Into」アイコンをクリックします。

 

.

PL/SQLプロシージャを実行する文に移動しました。 「Step Into」アイコンをクリックします。

 

.

DETERMINE_PRIMESプロシージャの次のブレーク・ポイントに到達しました。 P_IN_VALUESは、長さが10の配列であるため、ループは10回実行されます。Continue」アイコンを数回クリックして、Localsウィンドウ内の値が変化するのを確認します。

 

.

LocalsウィンドウのP_IN_VALUES変数名の隣にある「+」アイコンをクリックして、入力配列の内容を表示します。 これは、C#アプリケーションからこのストアド・プロシージャに渡された値の配列です。 しばらくの間、コードを進めます。 P_OUT_VALUES配列を開いて、最終的にこのストアド・プロシージャによって返される値が入力される様子を確認することもできます。

 

.

右下にあるウィンドウで、「Call Stack」タブをクリックします。 呼出し履歴を調べることで、プログラムの現在の実行ポイントまでのコード・パスを特定できます。

 

.

このブレーク・ポイントを無効にして、プログラムを次のブレーク・ポイントまで進めます。 ブレーク・ポイントを右クリックして、「Disable Breakpoint」を選択します。 赤い円のブレーク・ポイント・アイコンを直接クリックして、ブレーク・ポイントを削除することもできます。

 

.

Continue」アイコンをクリックして、プログラムを次のブレーク・ポイントまで実行します。

 

.

コードによってロジックが実行され、ユーザーに表示される内容が生成されます。 「Step Into」をさらに数回クリックします。

 

.

もう一度、「Continue」アイコンをクリックして、次のブレーク・ポイントに進みます。

 

.

ADD_NEW_JOBプロシージャのブレーク・ポイントに到達しました。

 

.

JOBS_REC PL/SQLレコードのグローバル変数を表示する場合は、ウォッチを作成する必要があります。 「jobs_rec」を選択して右クリックし、「Add Watch」を選択します。 次に、ウィンドウ下部にある「Watch」タブを選択します。

 

.

Watchウィンドウは、Visual Studioの組込みウィンドウで、特定のプログラム変数を調べることができます。 「jobs_rec」ウォッチを開きます。

 

.

Step Into」を4回クリックして、ウォッチに値が代入されることを確認します。 次に、「Continue」をクリックします。

 

.

プログラムの実行が終了すると、結果が表示されます。

まとめ

このチュートリアルで学習した内容は、以下のとおりです。

 

Hardware and Software Engineered to Work Together 会社情報 |オラクルとサン | Oracle RSS Feeds | 採用情報 | お問い合わせ | サイトマップ | 情報保護基本方針 | ウェブサイトのご使用条件 | 個人情報保護基本方針