how to delete user in SSRS using TSQL - reporting-services

I have some users in SSRS which I want to delete.
where I try to run:
DELETE FROM dbo.Users
WHERE dbo.Users.UserName = 'domain\user'
I'm getting the following error:
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint
"FK_Catalog_CreatedByID". The conflict occurred in database "ReportServer",
table "dbo.Catalog", column 'CreatedByID'.
The statement has been terminated.
How can I delete users (and all their permissions from SSRS database?

I run into the same problem that I wanted to permanently remove users from the SSRS database. So I made this SQL syntax (BACKUP YOUR DB BEFORE!):
DECLARE #username varchar(255); SET #username = '<username>';
DECLARE #ownerid uniqueidentifier; SET #ownerid = (SELECT UserID FROM Users WHERE UserName = #username)
BEGIN TRAN
UPDATE Subscriptions SET ModifiedByID = OwnerID WHERE ModifiedByID = #ownerid
DELETE FROM Subscriptions WHERE OwnerID = #ownerid
DELETE FROM Schedule WHERE CreatedById = #ownerid
DELETE FROM PolicyUserRole WHERE UserID = #ownerid
DELETE FROM Users WHERE UserID = #ownerid
COMMIT
Replace the <username> with the user you want to remove and that's it. But be aware that this also removes other data from this user as well.

The error is clear that you have data in other tables that references the Users table which you are trying to delete.
So you have two options:
Remove the constraints from the Users table and then delete the record and reapply all the constraints again.
Remove the data from the referenced tables where your User table is getting referenced.

select UserID, u.UserName
into #rs_users
from
ReportServer.dbo.Users as u
where userid = 1 -- expression
delete from [ReportServer].[dbo].[PolicyUserRole]
where UserID in (select UserID from #rs_users)
declare #user_name nvarchar(100), #pattern_start nvarchar(300), #pattern_end nvarchar(100), #result nvarchar(max)
declare #start_position int, #end_position int, #sec_data_id uniqueidentifier
DECLARE user_cursor CURSOR
FOR
select UserName
from #rs_users
OPEN user_cursor;
FETCH NEXT FROM user_cursor INTO #user_name
WHILE ##FETCH_STATUS = 0
BEGIN
set #pattern_start = '<Policy><GroupUserName>' + #user_name + '</GroupUserName><GroupUserId>'
set #pattern_end = '</Policy>'
DECLARE secdata_cursor CURSOR
FOR
select SecDataID
from
[ReportServer].[dbo].SecData as sec
where
sec.XmlDescription like '%' + #pattern_start + '%'
OPEN secdata_cursor;
FETCH NEXT FROM secdata_cursor INTO #sec_data_id
WHILE ##FETCH_STATUS = 0
BEGIN
select
#start_position = PATINDEX ( '%' + #pattern_start + '%' , XmlDescription ) ,
#end_position = CHARINDEX(#pattern_end, cast(XmlDescription as nvarchar(max)), #start_position),
#result = SUBSTRING ( XmlDescription , #start_position , #end_position+len(#pattern_end)-#start_position )
from [ReportServer].[dbo].SecData as sec
where SecDataID=#sec_data_id
-- replace user to empty
if #start_position > 0 and #end_position > 0 and len(#result) > 0
begin
update [ReportServer].[dbo].SecData
set XmlDescription = replace(cast(XmlDescription as nvarchar(max)),#result,'')
where SecDataID=#sec_data_id
end
FETCH NEXT FROM secdata_cursor INTO #sec_data_id
END;
CLOSE secdata_cursor;
DEALLOCATE secdata_cursor;
FETCH NEXT FROM user_cursor INTO #user_name
END;
CLOSE user_cursor;
DEALLOCATE user_cursor;

Related

Foreach Data in Field Insert Selected Field from One Database to Another in MySQL

I have two (2) databases of dissimilar Schematics,
db1 migrated from MSSQL to MYSQL
and
db2 created from Laravel Migration.
Here's the challenge:
The tables of db1 do not have id columns (Primary Key) like is easily found on db2 tables. So I kept getting the warning message:
Current selection does not contain a unique column. Grid edit, checkbox, Edit, Copy and Delete features are not available.
So I had to inject the id columns on the tables in the db1
I need to extract fields [level_name, class_name] from stdlist in db1,
Create levels (id,level_name,X,Y) on db2
classes (id,class_name,level_id) on db2
To throw more light: The level_id should come from the already created levels table
I have already succeeded in extracting the first instance using the following snippet:
First Query to Create Levels
INSERT INTO db2.levels(level_name,X,Y)
SELECT class_name as level_name,1 as X,ClassAdmitted as Y
FROM db1.stdlist
GROUP BY ClassAdmitted;
This was successful.
Now, I need to use the newly created ids in levels table to fill up level_id column in the classes table.
For that to be possible, must I re-run the above selection schematics? Is there no better way to maybe join the table column from db1.levels to db2.stdlist and extract the required fields for the new insert schematics.
I'll appreciate any help. Thanks in advance.
Try adding a column for Processed and then do a while exists loop
INSERT INTO db2.levels(level_name,X,Y)
SELECT class_name as level_name,1 as X,ClassAdmitted as Y, 0 as Processed
FROM db1.stdlist
GROUP BY ClassAdmitted;
WHILE EXISTS(SELECT * FROM db2.levels WHERE Processed = 0)
BEGIN
DECLARE #level_name AS VARCHAR(MAX)
SELECT TOP 1 #level_name=level_name FROM db2.levels WHERE Processed = 0
--YOUR CODE
UPDATE db2.levels SET Processed=1 WHERE level_name=#level_name
END
You may need to dump into a temp table first and then insert into your real table (db2.levels) when you're done processing. Then you wouldn't need the Unnecessary column of processed on the final table.
This is what worked for me eventually:
First, I picked up the levels from the initial database thus:
INSERT INTO db2.levels(`name`,`school_id`,`short_code`)
SELECT name ,school_id,short_code
FROM db1.levels
GROUP BY name
ORDER BY CAST(IF(REPLACE(name,' ','')='','0',REPLACE(name,' ','')) AS UNSIGNED
INTEGER) ASC;
Then I created a PROCEDURE for the classes insertion
CREATE PROCEDURE dowhileClasses()
BEGIN
SET #Level = 1;
SET #Max = SELECT count(`id`) FROM db2.levels;
START TRANSACTION;
WHILE #Level <= #Max DO
BEGIN
DECLARE val1 VARCHAR(255) DEFAULT NULL;
DECLARE val2 VARCHAR(255) DEFAULT NULL;
DECLARE bDone TINYINT DEFAULT 0;
DECLARE curs CURSOR FOR
SELECT trim(`Class1`)
FROM db1.dbo_tblstudent
WHERE CAST(IF(REPLACE(name,' ','')='','0',REPLACE(name,' ','')) AS UNSIGNED INTEGER) =#Level
GROUP BY `Class1`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN curs;
SET bDone = 0;
REPEAT
FETCH curs INTO val1;
IF bDone = 0 THEN
SET #classname = val1;
SET #levelID = (SELECT id FROM db2.levels WHERE short_code=#Level limit 1);
SET #schoolId = 1;
SET #classId = (SELECT `id` FROM db2.classes where class_name = #classname and level_id= #levelID limit 1);
IF #classId is null and #classname is not null THEN
INSERT INTO db2.classes(class_name,school_id,level_id)
VALUES(#classname,#schoolId,#levelID);
END IF;
END IF;
UNTIL bDone END REPEAT;
CLOSE curs;
END;
SELECT CONCAT('lEVEL: ',#Level,' Done');
SET #Level = #Level + 1;
END WHILE;
END;
//
delimiter ;
CALL dowhileClasses();
With this, I was able to dump The classes profile matching the previously created level_ids.
The whole magic relies on the CURSOR protocol.
For further details here is one of the documentations I used.

Error 1604 Creating MySQL Stored Procedure. MySQL Version 5.7.19

I am trying to translate a SQL stored procedure I have written in the past to MySQL. This error is giving me trouble.
I am using phpmyadmin 4.7.4 to create this procedure
The error I am getting is at SET userID = SELECT MAX(ID) + 1 FROM users I have also placed a tag before it in the code so it is easier for you guys to find.
The error that is outputted is:
MySQL said: Documentation
/#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET userID = SELECT MAX(ID) + 1 FROM users;
-- Default to 1 if the table is em' at line 13
CREATE PROCEDURE uspAddUser(username VARCHAR(50), email VARCHAR(50), password VARCHAR(50), avatar VARCHAR(50))
BEGIN
DECLARE userID INTEGER;
BEGIN
ROLLBACK; -- Rollback transaction on error
END;
START TRANSACTION
-- Get the next highest ID and lock the table until the end of the transaction
<ERROR> -> SET userID = SELECT MAX(ID) + 1 FROM users;
-- Default to 1 if the table is empty
SET userID = COALESCE(userID, 1);
-- CREATE new record
INSERT INTO users(userID, username, email, password, avatar)
VALUES(ID, email, password, avatar, 1); -- 1 = Active
-- return ID to calling program
SELECT userID AS ID;
COMMIT;
END;//
This is the original SQL query if you guys want to see that at all
GO
CREATE PROCEDURE uspAddTeam
#strTeam VARCHAR(50)
,#strMascot VARCHAR(50)
AS
SET NOCOUNT ON -- Report Only Errors
SET XACT_ABORT ON -- Rollback transaction on error
BEGIN TRANSACTION
DECLARE #intTeamID INTEGER
-- Get the next highest ID and lock the table until the end of the transaction
SELECT #intTeamID = MAX(intTeamID) + 1 FROM TTeams (TABLOCKX)
-- Default to 1 if the table is empty
SELECT #intTeamID = COALESCE(#intTeamID, 1)
-- CREATE new record
INSERT INTO TTeams(intTeamID, strTeam, strMascot, intTeamStatusID)
VALUES(#intTeamID, #strTeam, #strMascot, 1) -- 1 = Active
-- return ID to calling program
SELECT #intTeamID AS intTeamID
COMMIT TRANSACTION
GO
You can try this:
DROP PROCEDURE IF EXISTS `uspAddUser`;
DELIMITER //
CREATE PROCEDURE `uspAddUser` (username VARCHAR(50), email VARCHAR(50), password VARCHAR(50), avatar VARCHAR(50))
BEGIN
DECLARE `userID` BIGINT(20);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
START TRANSACTION;
-- Get the next highest ID and lock the table until the end of the transaction
SET userID = (SELECT MAX(ID) + 1 FROM users);
-- Default to 1 if the table is empty
SET userID = COALESCE(userID, 1);
-- CREATE new record
INSERT INTO users(userID, username, email, password, avatar)
VALUES(ID, email, password, avatar, 1); -- 1 = Active
-- return ID to calling program
SELECT userID AS ID;
COMMIT;
END//
DELIMITER ;
Question(s)
Does the table with ID is set as an auto-increment column? If not, please do.. because it will eliminate the part:
-- Get the next highest ID and lock the table until the end of the transaction
SET userID = (SELECT MAX(ID) + 1 FROM users);

Update in mysql trigger not working

I'm creating a trigger to execute after an insert is done into my checkin table but my update statement is not working
DELIMITER $$
DROP TRIGGER IF EXISTS checkins_AINS$$
CREATE TRIGGER `checkins_AINS` AFTER INSERT ON `checkins` FOR EACH ROW
BEGIN
DECLARE client_id INT;
DECLARE duplicate_record INTEGER DEFAULT 0;
DECLARE bpoints INT;
DECLARE business_id INT;
DECLARE CONTINUE HANDLER FOR 1062 SET duplicate_record = 1;
SELECT checkinPoints, id INTO bpoints, business_id FROM businesses WHERE id = new.venue_id;
INSERT INTO clients_checkins_summary(client_id, venue_id, first_checkin, last_checkin,visits)
VALUES(new.client_id, new.venue_id, new.createAt, new.createAt,1);
INSERT INTO clients_points_summary(client_id, business_id,current_points)
VALUES(new.client_id, business_id,bpoints);
IF duplicate_record = 1
THEN
UPDATE clients_checkins_summary
SET last_checkin = new.createAt,
visits = visits + 1
WHERE client_id = new.client_id and venue_id = new.venue_id;
UPDATE clients_points_summary
SET current_points = current_points + bpoints
WHERE client_id = new.client_id and business_id = business_id;
END IF;
END$$
DELIMITER ;
Inserting:
insert into checkins(client_id,venue_id,points,createAt,updateAt)
values (52,19,1,now(),now());
for the first time works fine but when the case of update is trigger is entering into the if but is not update the value.
I trace the variables into a table and all the values are correct but update is not been updating anything.
I missing something?
am I missing something?
Possibly this
UPDATE clients_points_summary
SET current_points = current_points + bpoints
WHERE client_id = new.client_id and business_id = business_id;
The problem here is that your local variable business_id and the column name clients_points_summary.business_id are ambiguous. You could disambiguate as follows:
UPDATE clients_points_summary cps
SET cps.current_points = cps.current_points + bpoints
WHERE cps.client_id = new.client_id and cps.business_id = business_id;

Check MySQL database for unique value over many tables

I'm looking for a way to easily check each table of a MySQL database and make sure that a certain field contains one value only. I have tables named Authors, Titles, Places, etc.
Each table contains a field called xuser and it needs to ask "does the field xuser contain the value xy in all records of all tables".
Can someone push me in the right direction how to do this with a SQL query if this is possible?
Thanks for reading, regards
Nico
I've created stored procedure which checks all table for provided db:
DELIMITER $$
DROP PROCEDURE IF EXISTS `UTL_CHECK_BACKUP_FOR_USER` $$
CREATE PROCEDURE `UTL_CHECK_BACKUP_FOR_USER`(
IN i_database_name VARCHAR(255),
IN i_user_column_name VARCHAR(255),
IN i_user_column_value VARCHAR(255),
OUT o_result TINYINT(1)
)
BEGIN
DECLARE v_table_name VARCHAR(255);
DECLARE v_last_row_fetched TINYINT(3) DEFAULT 0;
DECLARE tables_cursor CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_schema = i_database_name
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_last_row_fetched = 1;
SET v_last_row_fetched = 0;
OPEN tables_cursor;
SET #query =
CONCAT(
'SELECT SUM(IF(user_column=''',
i_user_column_value,
''', 1, -1)) = 1 INTO #o_result FROM ( SELECT ''test'' AS user_column FROM information_schema.tables WHERE 1<>1 '
)
;
table_loop: LOOP
FETCH tables_cursor INTO v_table_name;
IF (v_last_row_fetched = 1) THEN
LEAVE table_loop;
END IF;
SET #query =
CONCAT(
#query,
' UNION SELECT DISTINCT(',
i_user_column_name,
') AS user_column FROM ',
v_table_name
)
;
END LOOP table_loop;
CLOSE tables_cursor;
SET v_last_row_fetched=0;
SET #query =
CONCAT(
#query,
' ) all_xusers;'
)
;
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET o_result = COALESCE(#o_result, 0);
END $$
DELIMITER ;
Just deploy this stored procedure to database.
And then it could be executed in the following way:
-- db_name, user_column_name, user_column_value, result
call UTL_CHECK_BACKUP_FOR_USER('test', 'xuser', 'xxx', #result);
select #result;
To get the rows from all three tables where xuser has the same value in all three tables you could use:
SELECT *
FROM authors a
JOIN titles t
ON t.xuser = a.xuser
JOIN places p
ON p.xuser = t.xuser
If you want to look at a specific xuser value you could add the following WHERE clause:
WHERE a.xuser = 'xy'
The first thing comes to my mind:
select sum(if(xuser='xxx', 1, -1)) = 1
from (
select distinct(xuser) from authors
union
select distinct(xuser) from titles
union
select distinct(xuser) from places
) all_xusers;
This will return 1 (true) if all tables contains records belonging ONLY to 'xxx' user. Otherwise (if there is no 'xxx' records or there is some other user records) it will return 0 (false).

MySQL stored procedure INSERT issue

The following scenario applies:
CREATE TEMPORARY TABLE IF NOT EXISTS `smth_table` (
`login` VARCHAR(20),
`password` VARCHAR(20),
`type` INT(11),
`account_state` DECIMAL(12,4)
);
PREPARE Selection FROM
"INSERT INTO `smth_table`
(SELECT ta.`login`, ta.`password`, ta.`type`, ta.`account_state`
FROM tableA ta
INNER JOIN tableB tb ON tb.id_client = ta.id_client
WHERE tb.id_lot = ? AND ta.`type` MOD 2 = 0
AND ta.first_use = '0000-00-00 00:00:00'
AND ta.account_state = 0
LIMIT ?)";
SET #WHERE = var1;
SET #LIMIT = var2;
EXECUTE Selection USING #WHERE, #LIMIT;
DEALLOCATE PREPARE Selection;
DECLARE curs CURSOR FOR
SELECT `password` FROM `smth_table`;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN pin_curs;
get_pass: LOOP
FETCH curs INTO pass;
IF v_finished = 1 THEN
LEAVE get_pass;
END IF;
UPDATE tableA ta INNER JOIN tableB tb
ON tb.id_client = ta.id_client
SET `type` = `type` | 1,
`account_state` = `account_state` + 5
WHERE tb.id_lot = var1
AND `password` = pass;
END LOOP get_pass;
CLOSE curs;
END
Why, when I run this stored procedure, does the temp table populates with more then the limit? Keep in mind that I set the LIMIT with an IN variable passed through the procedure, and it's 10, incidentally. But when I run the procedure it inserts in the temp table more the 100 rows, and I don't understand why, when it should insert only 10.
SOLVED!
The issue relayed on the fact that I was not deleting the table upon creating it again, thus inserting same values over and over again...
DROP TABLE IF EXISTS `smth_table`;
this inserted before creating it and the query's run smooth :-)