I hve written a pl/sql procedure :
PROCEDURE xx_WriteBLOBToFILE (myfilename IN VARCHAR2,L_PERSON_ID IN NUMBER) IS
v_blob BLOB;
blob_length INTEGER;
out_file utl_file.file_type;
v_buffer RAW(32767);
chunk_size BINARY_INTEGER := 32767;
Blob_Position Integer := 1;
G_Zipped_Blob Blob;
B_Dl_File1 Blob;
BEGIN
-- Retrieve the BLOB for reading
Select Image Into V_Blob From Per_Images
Where Parent_Id =L_PERSON_ID;
-- Retrieve the SIZE of the BLOB
blob_length:=DBMS_LOB.GETLENGTH(v_blob);
-- Open a handle to the location where you are going to write the BLOB to file
-- NOTE: The 'wb' parameter means "write in byte mode" and is only availabe
-- in the UTL_FILE package with Oracle 10g or later
Out_File := Utl_File.Fopen ('**INT_DIR_IMG_BLOB**', Myfilename, 'wb', Chunk_Size);
-- Write the BLOB to file in chunks
WHILE blob_position <= blob_length LOOP
IF blob_position + chunk_size - 1 > blob_length THEN
chunk_size := blob_length - blob_position + 1;
End If;
DBMS_LOB.READ(v_blob, chunk_size, blob_position, v_buffer);
UTL_FILE.PUT_RAW(out_file, v_buffer, TRUE);
blob_position := blob_position + chunk_size;
END LOOP;
-- Close the file handle
Utl_File.Fclose (Out_File);
End;
I want to dynamically create the folder in /Blobfile in a location and then create the directory like INT_DIR_IMG_BLOB dynamically.
How can i create the folder in the server in plsql
If the operating system directory does not already exist, you probably can't create it directly in PL/SQL. You could create a Java stored procedure (or a .Net stored procedure if your database runs on Windows) that creates the operating system directory and call that from PL/SQL. You could also create a dbms_scheduler job that calls out to the operating system to create the directory and call that from PL/SQL.
Once the operating system directory exists, you can create the Oracle directory object using dynamic SQL. You'd also, presumably, need to grant privileges on that directory object to users dynamically.
execute immediate 'create directory ' || directory_name_you_want ||
' as ''' || directory_path || '''';
execute immediate 'grant read on ' || directory_name_you_want ||
' to some_role';
You could then use the newly created directory in your code.
Although you could do this, I would generally advise you not to go down this path. Dynamically creating objects at runtime is generally a poor idea, it's going to make your code a lot more complicated and much harder to support. And it creates lots of opportunities for things to go wrong in new and interesting ways.
You can use DBMS_SCHEDULER for create the folder in os.
1. create credentials.
2. write scheduler for external job execution.
BEGIN
DBMS_CREDENTIAL.CREATE_CREDENTIAL(
credential_name => 'credintial', ----- credintial name give by u
username => 'dons', ----- os username
password => 'password'); ----- os password
END;
/
CREATE OR REPLACE PROCEDURE PROC_MAKEFOLDER AS
BEGIN
DBMS_SCHEDULER.CREATE_JOB
(JOB_NAME=>'folder_maker', --- job name
JOB_ACTION=>'mkdir /home/anil/new_folder', --- executable file with path
JOB_TYPE=>'executable', ----- job type
NUMBER_OF_ARGUMENTS=>0, -- parameters in numbers
ENABLED=>false,
AUTO_DROP =>true,
CREDENTIAL_NAME=>'credintial', -- give credentials name which you have created before "credintial"
COMMENTS=> 'folder or os directory creation');
DBMS_SCHEDULER.RUN_JOB('folder_maker');
END ;
EXEC PROC_MAKEFOLDER;
Related
This question already has answers here:
Delphi Get file location
(2 answers)
Closed 6 years ago.
I am using SQLite, rather than MySQL, because it is simpler and requires no extra running software, just my executable.
For simplicity's sake I would prefer to have the database file in the same directory as my executable, and to be able to copy or move that folder elsewhere and still have the program work. Meaning that it can find the SQLite database file, which was copied along with it, in its new location.
However, it looks like I have to specify an absolute path to the database file.
Is there any way to change this at run time?
For those who don't quite follow that, I will try to explain:
let us say that my app's .exe is in C:\A\A.exe
so, I want to put the database file in the same directory. Lets call it C:\A\A.db
Delphi seems to require an absolute path. I.e, C:A\A.db and not .\A.db
I want to be able to copy both the .exe and its database to C:\B and still have the .exe be able to find its database file, which is now in C:\B\A.db
How can I do that programmatically, at run-time?
Answer
The path to the database is stored in the database connection component, so something like myConnection.parameters.database := 'C:\my_database.db;
Just compute the SQlite3 database file name on the fly, using:
myDbFileName := ExtractFilePath(paramstr(0)) + 'mysqlite3file.db3';
This will point e.g. to c:\my\app\folder\mysqlite3file.db3 file, when you run c:\my\app\folder\myprogam.exe.
First you want to copy the db to the EXE folder :
if FileExists(FDConnection1.Params.Database) then
CopyFile(Pchar(FDConnection1.Params.Database),Pchar('EXE Folder\A.db'),True);
then you can change the connection to the new db (copy) :
if FileExists('EXE Folder\A.db') then
begin
FDConnection1.Params.Database := 'EXE Folder\A.db';
FDConnection1.Connected := True;
end;
You always have to specify absolute path to the database file. Alternative would be preforming a full search for the database file which is stupid.
Here is a little piece of code I use to create backup of the database so you get the idea:
procedure TForm1.dxBarButton1Click(Sender: TObject);
var fileSource, fileDest,dirName: string;
begin
dirname := ExtractFilePath(Application.ExeName)+'\backup database' ;
if not directoryexists(dirName) then
CreateDir(dirName);
if MessageDlg('Create database copy ?'+ #13#10 +'Attention,new copy will overwrite existing one',
mtConfirmation, [mbYes, mbNo], 0, mbYes) = mrNo then
exit
else
try
dataModule2.ACRDatabase1.Close;
fileSource := ExtractFilePath(Application.ExeName)+'sgit.adb';
fileDest := ExtractFilePath(Application.ExeName)+'\backup database\sgit.adb';
If CopyFile(PChar(fileSource), PChar(fileDest), False) then begin
dataModule2.ACRDatabase1.Open;
dataModule2.FIRME.Open;
ShowMessage('Copy was made !');
end else
RaiseLastOSError;
except on E: Exception do
showMessage(Format('Error during copying : %s',[E.Message]));
end;
end;
So in your case you can write to an *.ini file where the database was copied to and then load the information during startup of your application. So basically you must always supply the database path (fileSource). How you do it is up to you. Just an idea ...
Note: I do not have this problem when using Oracle SQL Developer:: - But it is not the Standard here. So i must find a way to do this in PL/SQL Developer
When attempting to use PL/SQL developer (PL/SQL Developer - the program) to dynamically drop tables then create new ones using a create statement I consistently run into the error:
PLS-00103: ENCOUNTERED THE SYMBOL "/" THE SYMBOL "/" WAS IGNORED PLSQL
This is due to the "/" at the end of the dynamic sql.
If I remove the "/" from the end I receive an error:
ENCOUNTERED THE SYMBOL "CREATE"
What is the best method to get around this error inside PL/SQL Developer?
Thank You:
DECLARE
VE_TABLENOTEXISTS EXCEPTION;
PRAGMA EXCEPTION_INIT(VE_TABLENOTEXISTS, -942);
PROCEDURE DROPTABLE(PIS_TABLENAME IN VARCHAR2) IS
VS_DYNAMICDROPTABLESQL VARCHAR2(1024);
BEGIN
VS_DYNAMICDROPTABLESQL := 'DROP TABLE ' || PIS_TABLENAME;
EXECUTE IMMEDIATE VS_DYNAMICDROPTABLESQL;
EXCEPTION
WHEN VE_TABLENOTEXISTS THEN
DBMS_OUTPUT.PUT_LINE(PIS_TABLENAME || ' NOT EXIST, SKIPPING....');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
END DROPTABLE;
BEGIN
DROPTABLE('foo.foo_table');
END DROPTABLE;
/
CREATE TABLE foo.foo_table AS
(
SELECT STUFF, MORE_STUFF FROM not_foo_table
)
;
SELECT * FROM foo.foo_table
;
I have too PLSQL Developer.
I try to compile your procedure the way you post it and I get the same error, but if I remove the blank spaces before the "/" it works fine; like it don't recognize the "/".
So, I recommend you to change this:
END DROPTABLE;
/
For this:
END DROPTABLE;
/
I have data in an interface table that I need to copy over to the application table based on a set of criteria (project #, task_Number). I am able to access everything I need in a select statement. I am unsure of how to start the script. Any pointers would be wonderful. I havent written a PL/SQL script before.
Welcome to PLSQL!
How you write your script depends on the context from which it will be run.
If I am running a script through sqlplus I have some bolier plate which I have below which you might find starts you off.
set define off;
set serveroutput on;
declare
l_error varchar2(4094);
begin
dbms_output.put_line('Start of script named XXX');
--Select/Insert statements here
--commit
dbms_output.put_line('End of script named XXX');
EXCEPTION WHEN OTHERS THEN
l_error := NVL(SUBSTR(SQLERRM,0,990),'NULL');
dbms_output.put_line(l_error || ':-' || NVL(SUBSTR(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,0,3000),'NULL'));
rollback;
end;
Edit - this issue appears to be Windows 7 and Vista due to a bug (see here - Same issue reported)
Edit2 - I might be running into a similar issue users wee with PATH (I am not using PATH but same result - Unanswered question with similar issues
I have an Inno Setup script that uses an environment variable to locate a folder and delete the contents. When I try to expand the variable without elevated privileges I get this:
TEST_USER=%APPDATA%\PROG\USER_DATA (this is set in Windows)
If I run this as Admin (or change privileges to admin) I see:
TESTUSER=c:\users\username\appdata\roaming\PROG\USER_DATA
Googling %APPDATA% issues shows others have this issue, usually they hit this when used in PATH, something to do with the path not being set before it is requested.
I was hoping to avoid a complex routine of checking with pos if the return value contains %appdata%. But I think that might be my only solution.
cmd.exe - Example of the issue
This was my answer to make it work. However, please check the answer from #Tobias81 to InnoSetup, expand environment variable (taken from registry value using {reg:...} ) that works and offers a more generic solution.
I am making multiple modules first then combining later to making 1 executable with multiple components so a user can select an action. Due to this I need to check the current value of a variable not the registry value. Plus the registry still returns %APPDATA% as my screen shot.
So my answer was to just hunt for the appearance of %APPDATA% and deal with it.
Here is my debugging routine. Now I can find it and deal with it allowing me to find the value no matter if it was set by the parent or only set in windows.
procedure InitializeWizard;
var
test_user: string;
app_user: string;
folder_to_find: string;
begin
test_user := (ExpandConstant('{%TEST_USER}'));
app_user := (ExpandConstant('{%APPPDATA}'));
if (test_user <> '') AND (Pos(Uppercase('%APPDATA%'), Uppercase(test_user))=0) then
begin
folder_to_find := test_user;
MsgBox('Folder found : ' + folder_to_find + ' APPDATA STRING WAS NOT DETECTED', mbInformation, MB_OK)
end
else
if (test_user <> '') AND (Pos(Uppercase('%APPDATA%'), Uppercase(test_user))=1) then
begin
StringChangeEx(test_user, '%APPDATA%', '', True);
folder_to_find := app_user + test_user;
MsgBox('Folder found : ' + folder_to_find + ' APPDATA STRING WAS DETECTED & REMOVED!', mbInformation, MB_OK);
end
else
begin
MsgBox('The TEST_USER Environment is not set' + #13#10#13#10 + 'This process will now exit!',mbInformation, MB_OK)
Abort;
end;
end;
Good Afternoon,
I'm starting in the world of Qt and a Firebird database.And finish the driver installation process and perform operations onthe database insert, update and consultation.
When I started to make stored procedures and run them from Qt did not work. Does not fail and always us that everything was made perfect, but the database does not run.
I am programming in Linux using Qt 2.0.1 and Firebird 2.1
I create a simple stored procedure test which makes it an insert into a table. It works by running the console but when trying to run fromQt does not work and gives me no errors.The SQL code is:
SET TERM ^ ;CREATE PROCEDURE AGREEGAR_UNO AS BEGIN insert into JUEGO(CODIGO,ESCRUTINIO,ESTADO,FECHA,HORAINICIO) values (next value for GNECODIGOJUEGO,'111,123,154,169,178','Hi', current_date, current_time);END^SET TERM ; ^
GRANT EXECUTE ON PROCEDURE AGREEGAR_UNO TO SYSDBA;
The following code will use to connect to firebird from Qt
bool VentanaPrueba::conectar()
{
this->db= QSqlDatabase::addDatabase("QIBASE","Data");
this->db.setDatabaseName("./BD/Data.fdb");
this->db.setPassword("password");
this->db.setUserName("SYSDBA");
if(!db.open())
{
return false;
}
else
return true;
}
And this is the code that is responsible for calling the procedure
void VentanaPrueba::procedimiento()
{
if (!this->db.isOpen()) this->conectar();
if(this->db.isOpen())
{ QSqlQuery procedimiento = QSqlQuery::QSqlQuery(this->db);
bool bandera = procedimiento.prepare("EXECUTE PROCEDURE AGREEGAR_UNO");
QString err = procedimiento.lastError().text();
bool respuesta= procedimiento.exec();
//this->db.commit();
if(!respuesta)
{
this->db.close();
}else
{
procedimiento.finish();
this->db.commit();
this->db.close();
}
}else{
//error
}
}
Thank you very much for your help.
IBPP or InterBase Plus Plus is a client interface project which connects for Qt with Interbase database system like firebird. Using it you can easily use your firebird database. Download its source code package from http://sourceforge.net/projects/ibpp/files/ or ibpp official site, and unpack. Copy the core folder into your project folder. And add these files in your Qt project.
Read complete guide at
https://rongsheng007.wordpress.com/2010/08/23/make-qt-applications-work-with-firebird-database/
I can't tell if this works for firebird, but you could try the following:
procedimiento.prepare("BEGIN EXECUTE PROCEDURE AGREEGAR_UNO; END;");
This is similar to the PL/SQL passage
BEGIN
EXECUTE PROCEDURE AGREEGAR_UNO;
END;
I am accessing Oracle databases with Qt and had to include the "BEGIN" and "END;" commands there. You don't have the "EXECUTE PROCEDURE" in oracle, but it might be required for Firebird.
Also, I am using Qt 4 so there might be a difference as well.
There is a simpler way, even though little bit weird.
Create a stored procedure in firebird with some output variable to suspend, and a VARCHAR(1024) input variable to pass the procedure call.
And call it in Qt with procedure call as a string parameter.
SET TERM ^ ;
create PROCEDURE SP_EXECUTE (STMNT varchar(1024) )
RETURNS (
INRETURN integer )
AS
BEGIN
execute statement stmnt;
inReturn=1;
suspend;
END^
SET TERM ; ^
}
Then in Qt,
procedimiento.prepare("SELECT INRETURN FROM SP_EXECUTE('EXECUTE PROCEDURE AGREEGAR_UNO')");