- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-18-2015 11:44 PM
Hi ServiceNow Developers,
I want to remove the existing duplicate records from User Role table(sys_user_has_role) table.
Please Suggest.
Thanks!
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-19-2015 01:39 AM
Firstly don't use a variable names "gr" in a Background Script. There is a known issue with this.
Secondly, you should consider whether this is something you really should be doing?
The platform deliberately creates multiple sys_user_has_role records, it's be design, so by trying to fix you are breaking something else.
For example if John is a member of the Network team and the Database team, he may have the itil role twice (two records in the sys_user_has_role table). Each one will track which group assigned him the role. If you hack the platform so he only has one record, let's say you delete the one corresponding to the Network team, he is only left with the one corresponding to the Database team. If John is then removed from the Database team the platform will remove his remaining sys_user_has_role record and he won't have the itil role anymore even tho he is still in the Networks team!
Thirdly your code is pretty inefficient, optimise it with GlideAggregate:
// Group the user role records by user/role combo
var userRoleGA = new GlideAggregate('sys_user_has_role');
userRoleGA.groupBy('user');
userRoleGA.groupBy('role');
userRoleGA.query();
var userRoleGR;
while (userRoleGA.next()) {
// Fetch the records for this user/role pair
userRoleGR = new GlideRecord('sys_user_has_role');
userRoleGR.addQuery('user', userRoleGA.user);
userRoleGR.addQuery('role', userRoleGA.role);
userRoleGR.query();
userRoleGR.next(); // Skip the first result
while (userRoleGR.next()) { // delete the rest
userRoleGR.deleteRecord();
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-19-2015 12:26 AM
Yes , you may need to add sys_id filter to skip one row but delete other rows
var gr = new GlideRecord('sys_user_has_role');
//gr.addQuery('user.user_name','admin') ; //remove comment and test this script for one user
//gr.addQuery('role','itil') ; //if you want to test for a role
gr.query();
while(gr.next()){
var gr2 = new GlideRecord('sys_user_has_role') ;
gr2.addQuery('user',gr.user);
gr2.addQuery('role',gr.role);
gr2.addQuery('sys_id','!=',gr.sys_id); // skipping 1 row
gr2.deleteMultiple();
}
You could also test for a particular role by adding filter
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-19-2015 12:56 AM
The issue is still the same. Its deleting all the records.
For example: I have 2 records for itil. Above script(while loop) is running for both records. So deleting both.
Earlier i was thinking if 2nd record will be deleted, while loop will not run for 2nd record to delete the 1st one.
However this is happening.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-19-2015 01:10 AM
Confirm that those 2 records belongs to same user having role itil. Ideally the script provided in last reply should work . I tested this on our instance and its working fine.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-19-2015 01:39 AM
Firstly don't use a variable names "gr" in a Background Script. There is a known issue with this.
Secondly, you should consider whether this is something you really should be doing?
The platform deliberately creates multiple sys_user_has_role records, it's be design, so by trying to fix you are breaking something else.
For example if John is a member of the Network team and the Database team, he may have the itil role twice (two records in the sys_user_has_role table). Each one will track which group assigned him the role. If you hack the platform so he only has one record, let's say you delete the one corresponding to the Network team, he is only left with the one corresponding to the Database team. If John is then removed from the Database team the platform will remove his remaining sys_user_has_role record and he won't have the itil role anymore even tho he is still in the Networks team!
Thirdly your code is pretty inefficient, optimise it with GlideAggregate:
// Group the user role records by user/role combo
var userRoleGA = new GlideAggregate('sys_user_has_role');
userRoleGA.groupBy('user');
userRoleGA.groupBy('role');
userRoleGA.query();
var userRoleGR;
while (userRoleGA.next()) {
// Fetch the records for this user/role pair
userRoleGR = new GlideRecord('sys_user_has_role');
userRoleGR.addQuery('user', userRoleGA.user);
userRoleGR.addQuery('role', userRoleGA.role);
userRoleGR.query();
userRoleGR.next(); // Skip the first result
while (userRoleGR.next()) { // delete the rest
userRoleGR.deleteRecord();
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-13-2017 09:32 AM