Cursor and SUBSTR usage in procedure - plsql

I need to trim instance name from complete dblink name .For example The select query returns result like HHVISDEV.TRINITI.COM. I need to get HHVISDEV. And ofcourse There are such multiple results. So I need to use cursor and print the final result. I am getting Warning: Procedure created with compilation errors., when I compile. And when I call the procedure I am getting ERROR at line 1:
ORA-06575: Package or function DELETEDBLINKS1 is in an invalid state. Can any one please guide me.
create or replace procedure DeleteDBLinks1 is
cursor mycursor is
SELECT SUBSTR(DB_LINK, 1, INSTR(DB_LINK, '.', 1, 1) - 1)
FROM dba_db_links;
myvar dba_db_links.dblinks%TYPE;
BEGIN
OPEN mycursor;
LOOP
FETCH mycursor
INTO myvar;
EXIT WHEN mycursor%NOTFOUND;
DBMS_OUTPUT.put_line(myvar);
END LOOP;
CLOSE mycursor;
end;
/

If you see Warning: Procedure created with compilation errors, then, I can guess, you compile your procedure in SQL*Plus. In SQL*Plus you can run command
show errors
and you will see errors list. Your procedure looks OK, so I think problem is - you have no access to dba_db_links view. Try to use all_db_links or user_db_links instead.

Along with what Dmitry said about you probably not having access to dba_db_links table, you also had a typo in the myvar variable definition. It should have been:
myvar dba_db_links.db_link%TYPE;
SQL*Plus> SHOW ERRORS will help you in your PL/SQL endeavors, until you start using a PL/SQL IDE like SQL Developer or (my favorite) PL/SQL Developer, which will show you the errors automatically.

Related

Delphi FireDAC error working with parameters SQLite

Good morning.
I'm with a problem that I can't figure out. The situation is the following:
I have a procedure that I call passing it a string, which is basically the name of a table.
In this particular case it is "sys".
This procedure basically executes the following lines:
Query.Close ();
Query.ParamByName ('TABLE'). AsString: = Table;
Query.Open;
"Query" basically has this:
SELECT * FROM: TABLE;
Therefore you should run the following:
SELECT * FROM sys;
Truth?
Well, apparently I'm having a bug. Since when testing it and executing my procedure this happens:
[FireDAC] [Phys] [SQLite] ERROR: near ": TABLE:" syntax error.
** Does SQLite work differently with parameters? **
I can not find why it fails.
Base of SQLite document and this link you can't pass table name as parameter:
[https://stackoverflow.com/questions/5870284/can-i-use-parameters-for-the-table-name-in-sqlite3][1]
Instead of that you can make your string of query by this manner(trick):
Query.sql[1]:='tablename'
Default query string my be like this:
select * form
//X (line 1 )
where ....

Which tool of Progress Developer Studio for OpenEdge can I use for testing ABL queries?

I've just written following erroneous ABL query:
FOR EACH T1 (WHERE T1.some-date = ' ') AND
(integer(T1.num1) >= 100) AND
(integer(T1.num1) <= 200) AND
(T1.some-other-date = 01/12/2021) AND
(T2.Name = itsme),
EACH T2 WHERE T2.num2 = T1.num2
BY T1.num1
As you can see, this is wrong because I've put the first bracket in front of "WHERE" instead of behind it. In top of that, my name "itsme", is not put between quotes, so the ABL query will never work.
I've been looking in my development environment ("Tools" menu), but I couldn't find an ABL query tester. I've also checked the directory "C:\Progressx86\OpenEdge\bin", but being a newbie I didn't find anything.
I have downloaded the "DataDigger" application, which contains a so-called "MCF Query Tester", but this only works on single table and only checks criteria, not entire ABL queries.
Does anybody know where I can find an ABL query tester, first for syntax checking (the bracket in front of the "WHERE") and (if possible) for data testing (01/12/2021, is that January 12th or December 1st?)?
Thanks in advance
Dominique
Create a new OpenEdge project in Progress Developer Studio for Openedge. Create a new ABL procedure under the project with the necessary database connection. Copy the above ABL code into the procedure file and you should be able to see the errors and warnings in your procedure file.
The ABL Scratch Pad view of Progress Developer Studio allows to execute ad-hoc queries.
https://knowledgebase.progress.com/articles/Knowledge/000055088
You don't mention which editor you're using, but in general terms, the ABL COMPILE statement performs syntax checking. There's no separate/independent executable that compiles/checks syntax. Generally you'll need to write a .P to perform the compilation.
You can use the PCTCompile Ant task if you'd like to use an Ant- or Gradle-based build system.
As to date formats, I thought that was in the doc, but no. Dates always have a MM/DD/YYYY format when hard-coded; decimals always use a . decimal separator (ie 123.45) when hard-coded.
Another way to test a query you're working on would be to use query-prepare which accepts a string.
DEFINE QUERY q-Test FOR T1, T2.
QUERY q-test:HANDLE:QUERY-PREPARE("your query string here").
One of my colleagues showed me an incredible easy solution:
Copy the query in a separate procedure window and add the results you want to see, something like this:
FOR EACH T1 (WHERE T1.some-date = ' ') AND
(integer(T1.num1) >= 100) AND
(integer(T1.num1) <= 200) AND
(T1.some-other-date = 01/12/2021) AND
(T2.Name = itsme),
EACH T2 WHERE T2.num2 = T1.num2
BY T1.num1
/* To be added for viewing results */
DISPLAY T1.Field1 T1.Field2 T2.Field5
END.
And launch this inside the programming environment (F2).
In case of syntax mistakes, the compiler shows the errors. In case the syntax is correct, a pop-up window is started, showing the results.

PL/SQL Perfom TRIM inside of a trigger

I am trying to make a trigger that when data is inserted, it trims the data that is being inserted.
Here is what I am trying ..
CREATE OR REPLACE TRIGGER trig_trim
BEFORE INSERT ON triggertest
FOR EACH ROW
BEGIN
TRIM(:new.testchar);
END;
/
I do an insert like this
INSERT INTO triggertest (testnum, testchar) VALUES (9, ' r9 ');
and I am getting this error...
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger.
When I just run the code to create the trigger I get this
TRIGGER TRIG_TRIM compiled
Errors: check compiler log
and in the compiler log it says "'TRIM' is not a procedure or is undefined"
Is my syntax wrong or my logic? I don't know why this is failing.
Your assignment syntax is wrong. Try this:
:new.testchar := TRIM(:new.testchar);
TRIM has to return the result to something. I think you want:
:new.testchar := TRIM(:new.testchar);

Two tables with different names and using the single record cannot be created, how can I implent this?

I'm trying to create two tables using the same record, with two different names, but it creates only any one of them or sometimes throws an exception.
Following is the code from my record file:
-record(account,{acctnum, cnic, name, address,date ,time, balance=0}).
Following is my code from module called accounts:
-module(accounts).
-compile(export_all).
-include("records.hrl").
start()->
ets:new(current,[named_table,{keypos, #account.cnic}]),
ets:new(savings,[named_table,{keypos, #account.cnic}]).
Sometimes it returns an atom called savings, but sometimes it gives the following error:
** exception error: bad argument
in function ets:new/2
called as ets:new(current,[named_table,{keypos,3}])
in call from accounts:start/0 (accounts.erl, line 5)
Please do let me know that either it's possible to create two tables in ets using a single record?
If not, then how can I Implement it, I'm trying to create two tables, one for the savings account and other for the current account, how can I resolve this problem?
There is not problem with creating two ETS based on one record.
** exception error: bad argument
in function ets:new/2
called as ets:new(current,[named_table,{keypos,3}])
in call from accounts:start/0 (accounts.erl, line 5)
Such exception usually means that the table with the same name is already created. I.e. function start was called twice (first one successfully, and second one - not).
When you execute start for the first time, everything is ok, and you get the result the last line of the function. You can check this by using the tv module; execute tv:start() and you can inspect any ets or mnesia table.
If you execute start again, then as Alexey says, you will get an error because the table current (and saving) already exists. This maks the shell crash, and destroy the 2 tables; so the next time you will use start, it will be ok again.
If you cannot know if the ets table is already existing, you can test it with a code like this:
ensure(T,Def) ->
case ets:info(T) of
undefined -> ets:new(T,Def);
_ -> ets:delete_all_objects(T) %% or anything you need to do in this case
end.

XQuery Update: insert or replace depending if node exists not possible?

I am trying to build simple XML database (inside BaseX or eXist-db), but I have trouble figuring how to modify values in document :
content is simple as this for test :
<p>
<pl>
<id>6></id>
</pl>
</p>
I am trying to build something like function which would insert element into <pl> if that element is not present or replace it if it is present. But XQuery is giving me troubles yet :
When I try it head-on with if-then-else logic :
if (exists(/p/pl[id=6]/name)=false)
then insert node <name>thenname</name> into /p/pl[id=6]
else replace value of node /p/pl[id=6]/name with 'elsename'
I get error Error: [XUDY0027] Replace target must not be empty. Clearly I am confused, why the else part is evaluated in both cases, thus the error.
When I empty out the else part :
if (exists(/p/pl[id=6]/name)=true)
then insert node <name>thenname</name> into /p/pl[id=6]
else <dummy/>
Then I get Error: [XUST0001] If expression: no updating expression allowed.
When I try through declaring updating function, even then it reports error :
declare namespace testa='test';
declare updating function testa:bid($a, $b)
{
if (exists(/p/pl[id=6]/name)=true)
then insert node <name>thenname</name> into /p/pl[id=6]
else <dummy/>
};
testa:bid(0,0)
Error: [XUST0001] If expression: no updating expression allowed.
I've got these errors from BaseX 6.5.1 package.
So how can I modify values in a simple fashion if possible ?
If I call insert straight, the there could be multiple elements of same value.
If I call replace it will fail when the node does not exist.
If I delete the node before insert/replace then I could destroy sub-nodes which I don't want.
In most SQL databases, these are quite simple task (like MYSQL 'replace' command).
#Qiqi: #Alejandro is right. Your if expression is incorrect XQuery syntax:
if (exists(/p/pl[id=6]/name))
then insert node <name>thenname</name> into /p/pl[id=6]
else replace value of node /p/pl[id=6]/name with 'elsename'
Note that eXist-db's XQuery Update functionality is currently an eXist-specific implementation, so in eXist (currently) 1.4.x and 1.5dev, you'll want:
if (exists(/p/pl[id=6]/name))
then update insert <name>thenname</name> into /p/pl[id=6]
else update value /p/pl[id=6]/name with 'elsename'
This eXist-specific XQuery Update syntax is documented on http://exist-db.org/update_ext.html. This syntax was developed before the W3C XQuery Update spec had reached its current state. The eXist team plans to make eXist fully compliant with the W3C spec soon, but in the meantime the docs above should help you achieve what you need to if you use eXist.
Note too that your example code contains a typo inside the pl and id elements. The valid XML version would be:
<p>
<pl>
<id>6</id>
</pl>
</p>

Resources