I have a master detail Interactive Grid, all is working fine. As soon as I select a row on the master it populates the details interactive grid without a problem.
The thing I'm trying to achieve is that I want to select two or more rows on the master and populate all the data on the details grid.
Is it possible?
I found your question very challenging and it can be useful to other users.
I'm not sure if the proposed solution works under every condition since it is not tested enough. I resolve your problem with APEX_COLLECTIONS, some JS and PL/SQL.
But lets start in the example below I will use the standard HR data set, more precisely the DEPARTMENTS and EMPLOYEEStables.
In the Before Header section add one process defined as:
BEGIN
APEX_COLLECTION.CREATE_OR_TRUNCATE_COLLECTION(
p_collection_name => 'SELECTED_MASTER');
END;
Also create one Ajax Callback process, name it SELECTOR:
BEGIN
APEX_COLLECTION.TRUNCATE_COLLECTION(p_collection_name => 'SELECTED_MASTER');
FOR i IN 1..apex_application.g_f01.count LOOP
APEX_COLLECTION.ADD_MEMBER ( p_collection_name => 'SELECTED_MASTER',
p_n001 => apex_application.g_f01(i));
END LOOP;
htp.p('Done.');
END;
Create the first IG: Load Dept
under Source section set the following values:
Location : Local Database
Type : Table/View
Table Owner : Parsing Schema
Table Name : Department
Columns:
APEX$ROW_SELECTOR (!important)
APEX$ROW_ACTION
DEPTNO
DNAME
LOC
Static ID : loadDept
on the IG create a DA:
Name : SELECT_ROWS
Event : Selection Change [Interactive Grid]
Selection Type : Region
Region : Load Dept
now add one True action which executes the following JS:
var array = []
var i;
for (i = 0; i < this.data.selectedRecords.length; i++) {
array[i] = this.data.selectedRecords[i][0];
}
apex.server.process( "SELECTOR", {
f01: array,
},
{
dataType : 'text',
success: function( data ) {
apex.region( "loadEmp" ).refresh();
},
error: function( jqXHR, textStatus, errorThrown ) {
apex.message.clearErrors();
apex.message.showErrors([
{
type: "error",
location: "page",
message: errorThrown,
unsafe: false
}
]);
}
} );
The second IG: Load Emp
Static ID : loadEmp
under Source section set the following values:
Location : Local Database
Type : SQL Query
SQL Query
SELECT EMPNO,
ENAME,
JOB,
MGR,
HIREDATE,
SAL,
COMM,
DEPTNO,
CREATED,
LAST_UPDATED
FROM EMPLOYEES
WHERE
APEX_COLLECTION.COLLECTION_MEMBER_COUNT ('SELECTED_MASTER') = 0
OR
(
APEX_COLLECTION.COLLECTION_MEMBER_COUNT ('SELECTED_MASTER') > 0
AND
EXISTS (SELECT 'x' FROM apex_collections
WHERE collection_name = 'SELECTED_MASTER' AND n001 = DEPTNO)
)
Although it works the first record in the master table is always selected, and that is the only known bug or feature. :)
Related
I have problem while I use SELECT query. Unfortunettly, the ID is store as VARCHAR which is big mistake and right now I have problem in following function
FUNCTION GET_SUB_PROJECTS(p_currentUserId IN VARCHAR,p_projectId IN INT)
RETURN SYS_REFCURSOR IS
rc SYS_REFCURSOR;
-- getSubProject
BEGIN
OPEN rc FOR
SELECT
p.*,
a.number_ AS activityNumber,
a.description AS activityDescription
FROM
projects p
LEFT JOIN
project_users_schedule_dates pusd
ON
pusd.ProjectID = p.ProjectID AND pusd.UserID = p_currentUserId
LEFT JOIN
activities a
ON
a.id = p.activity
LEFT JOIN
responsible_persons rp
ON
rp.ProjectID = p.ProjectID AND rp.UserID = p_currentUserId
LEFT JOIN
users u
ON
u.UserID = p_currentUserId
WHERE
(u.User_roleID = 1 AND
p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
OR
((
(p.Responsible_person_id = p_currentUserId OR p.Delivery_contact = p_currentUserId OR rp.UserID = p_currentUserId OR (pusd.UserID = p_currentUserId AND SYSTIMESTAMP BETWEEN TO_DATE(pusd.StartDate,'YYYY-MM-DD') AND TO_DATE(pusd.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY AND
SYSTIMESTAMP BETWEEN TO_DATE(p.StartDate,'YYYY-MM-DD') AND TO_DATE(p.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY))
)
AND
p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
ORDER BY p.CustomName;
RETURN rc;
END GET_SUB_PROJECTS;
When I call function it needs to return data, but it doesn't. Somehow, here p.Responsible_person_id and p.Delivery_contact needs to be NUMBER but somehow it is VARCHAR
When I call function I use
SELECT PROJECT_PACKAGE.GET_SUB_PROJECTS('199',141) FROM DUAL
I found one solution to modify but It throw me error like
Error report -
ORA-01439: column to be modified must be empty to change datatype
01439. 00000 - "column to be modified must be empty to change datatype"
What to do in this situation ? What is the best method to solve this issue ?
You can change the data type of a column online using dbms_redefinition
create table t (
c1 varchar2(10)
primary key
);
create table t_new (
c1 number(10, 0)
primary key
);
insert into t values ( '1.0000' );
commit;
begin
dbms_redefinition.start_redef_table (
user, 't', 't_new',
col_mapping => 'to_number ( c1 ) c1',
options_flag => dbms_redefinition.cons_use_rowid
);
end;
/
exec dbms_redefinition.sync_interim_table ( user, 't', 't_new' );
exec dbms_redefinition.finish_redef_table ( user, 't', 't_new' );
desc t
Name Null? Type
C1 NOT NULL NUMBER(10)
select * from t;
C1
1
There are also options to copy constraints, triggers, indexes, etc. automatically in this process.
I have a oracle apex report which fetches two rows every time.
I want to highlight all the columns where data is different in two rows.
So when user looks at the comparison report he don't have to go through all the columns to identify where data has been changed.
I have tried to look at the apex features and some javascript code but was unable to do so reliably.
You can have a look at sample report here:
https://apex.oracle.com/pls/apex/f?p=128616:8:109311280077805:::::
go to page "help me with comparison"
I want to highlight the benefit name column as data is different in benefit name column.
if your table has id "test" you can try call this function on page load compareRows(document.getElementById('test'));
the function body:
function compareRows(table) {
var row1,row2, rows = table.rows;
var cell1,cell2;
var rowText;
row1=rows[1];
row2=rows[2];
cell1=row1.cells;
cell2=row2.cells;
for (var i=0; i<cell1.length; i++) {
if(cell1[i].textContent != cell2[i].textContent){
cell1[i].style.backgroundColor = "red";
cell2[i].style.backgroundColor = "red";
}
}
}
You can use the analytic function "LAG" to reference the previous row in your resultset.
So one possible solution is to (1) select the value of the current row and the value of the previous row, (2) compare the 2 columns and set a flag, only in row 2 because that is where you want to highlight, (3) use highlighting in apex to indicate which columns have different values. See example sql below for an example.
-- create tables
create table so_dummy_data (
id number generated by default on null as identity
constraint so_dummy_data_id_pk primary key,
name varchar2(100) not null,
email varchar2(100) not null
)
;
-- load data
insert into so_dummy_data (
id,
name,
email
) values (
1,
'John Doe',
'john.doe#mail.com'
);
insert into so_dummy_data (
id,
name,
email
) values (
2,
'John Doe',
'john.x.doe#mail.com'
);
commit;
WITH old_and_new AS
(SELECT
id,
name,
LAG(name,1)OVER(
ORDER BY
name
)AS new_name,
email,
LAG(email,1)OVER(
ORDER BY
1
)AS new_email,
row_number() over (order by 1) rn
FROM
so_dummy_data
)
SELECT
name,
CASE
WHEN rn = 1 THEN 'N'
WHEN name = new_name THEN
'N'
ELSE
'Y'
END AS name_changed,
email,
CASE
WHEN rn = 1 THEN 'N'
WHEN email = new_email THEN
'N'
ELSE
'Y'
END AS email_changed
FROM
old_and_new;
I have question on classic report, which is based on multiple table joins. On which I have written process to loop and insert only checked box item. but it only select first item. However if do this on a single table it work properly. I would appreciate if someone can help me on inserted selected record when query is based on multiple joins.
My query is as below.
select apex_item.checkbox2(1, ord.rowid) sel,
apex_item.text(2,cust.name) Customer,
apex_item.text(3, it.item_id) Item,
apex_item.text(4,it.product_id) Product,
apex_item.text(5,price) price,
apex_item.text(6,quantity)||apex_item.hidden(7,ord.id) qty
from s_ord ord,
s_item it,
s_customer cust
where ord.id=it.ord_id
and cust.id=ord.customer_id
My process is as follow;
for i in 1..apex_application.g_f01.count loop
APEX_DEBUG_MESSAGE.LOG_MESSAGE(p_message => 'G_F01 : '||APEX_APPLICATION.G_F01(i), p_level => 1);
APEX_DEBUG_MESSAGE.LOG_MESSAGE(p_message => ' Q1 : '||APEX_APPLICATION.G_F02(i), p_level => 1);
APEX_DEBUG_MESSAGE.LOG_MESSAGE(p_message => ' P1 : '||APEX_APPLICATION.G_F03(i), p_level => 1);
end loop;
end;
As far as I can tell, you can't do that if a tabular form is created as a JOIN of two (or more) tables (didn't investigate why).
Here's what I do:
I base my tabular form on one table (the one I'm planning to work (insert, update) with
columns, that are normally fetched from other tables (using JOINs) are displayed using functions
That fixes the issue.
For example: you want to update employee's information, but also display department name they work in.
Don't:
select e.empno,
e.ename,
d.dname,
e.sal
from emp e join dept d on e.deptno = d.deptno;
Do:
create function f_dname (par_deptno in dept.deptno%type)
return dept.dname%type
is
retval dept.dname%type;
begin
select max(d.dname)
into retval
from dept d
where d.deptno = par_deptno;
return retval;
end;
/
select e.empno,
e.ename,
f_dname (e.deptno) dname, --> function instead of DEPT.DNAME
e.sal
from emp e; --> no join
I hope it'll help.
CREATE OR REPLACE
PROCEDURE "UNASSIGN_CUSTOMER_FEATURES"
(CustomerID_Param IN NUMBER, FeatureID_Param IN NUMBER, WalletID_Param IN NUMBER)
AS
BEGIN
DELETE FROM CUSTOMER_EXTRA_FEATURES WHERE FEATURES_ID = FeatureID_Param
AND CUSTOMER_ID = CustomerID_Param;
MERGE INTO CUSTOMER_SERVICE_CONFIG c
USING
(SELECT BUSINESS_SERVICE_CONFIG.ID from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param ) ids
ON (c.SERVICE_CONFIG_ID = ids.ID and c.CUSTOMER_ID = CustomerID_Param )
WHEN MATCHED THEN
DELETE WHERE CUSTOMER_ID = CustomerID_Param AND SERVICE_CONFIG_ID = ids.ID;
END;
You are missing an UPDATE statement prior to doing a DELETE
something like
WHEN MATCHED THEN
UPDATE SET <some field> with <some value>
DELETE WHERE CUSTOMER_ID = CustomerID_Param AND SERVICE_CONFIG_ID =ids.ID;
END;
Refer the following url:
Oracle sql merge to insert and delete but not update
Hope that helps!
The syntax diagram for the merge statement shows that you the delete clause is an optional part of the update, not standalone:
You're getting the "ORA-00905: missing keyword" error because you don't have an update. You could put in a dummy update, but it looks like you really want to delete all rows that match, with no updates to other rows or inserts of new rows; which would be simpler as a plain delete, something like:
DELETE FROM CUSTOMER_SERVICE_CONFIG c
WHERE CUSTOMER_ID = CustomerID_Param
AND SERVICE_CONFIG_ID IN (
SELECT BUSINESS_SERVICE_CONFIG.ID from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param );
or
DELETE FROM CUSTOMER_SERVICE_CONFIG c
WHERE CUSTOMER_ID = CustomerID_Param
AND EXISTS (
SELECT null from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param
WHERE BUSINESS_SERVICE_CONFIG.ID = c.SERVICE_CONFIG_ID );
I'm using datatables with server side processing in a Laravel project. My status column is integer, which is then formatted
->editColumn('status', function($orders) use ($statuses) {
return $statuses[$orders->status];
})
But this approach prevents status column from being used in search.
Is sthere a way to join query with fake table? Smth like this
->join('fake_status_table', 'production_orders.status', '=', 'fake_status_table.id')
Drafting two solutions
Solution #1
$orders= DB::table('production_orders')
->select(DB::raw("DECODE (status_id, 1, 'No started',
2, 'Running',
3, 'Done',
4, 'Defect')"))
solution #2
//create tamporary table
$status_table = DB::insert( DB::raw( "CREATE TEMPORARY TABLE statuses") );
$orders = \DB::table('production_requests')
// join it with drawing table
->join('statuses', 'production_requests.status', '=', 'statuses.id')
// Generate result
$result = Datatables::of($orders)->make(true);
// KILL TEMPORARY TABLE
$dropTable = DB::unprepared( DB::raw( "DROP TEMPORARY TABLE statuses" ) );
// RETURN RESULT
return $result;
Views is nothing but a temporary table..
But it was copy of the table itself.. You shall create a view according to your need.. If you want to have the view of your entire table .. then
CREATE VIEW test.v AS SELECT * FROM t;
Or even
CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
Then you shall return some data from the controller and construct the coloumn as we do usual in the datatables
Like this
Jquery :
$(document).ready(function() {
$('#example').DataTable();
} );
And then foreach for the table !!
Hope this helps you