SQL Server - Get Database role membership from orphaned UserSID - tsql

I am currently using the following code within SQL Server 2005 to obtain data on orphaned user SID's, this works well but I really need to get information on role memberships for each orphaned userSID, is this possible and if so, how can I write a query for this?
DECLARE cur CURSOR FAST_FORWARD FOR
SELECT name FROM sys.databases
WHERE database_id > 4
OPEN cur
DECLARE #SQL NVARCHAR(MAX), #DBName SYSNAME
DECLARE #Results TABLE (DBName SYSNAME, UserName SYSNAME, UserSID VARBINARY(MAX))
FETCH NEXT FROM cur into #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'USE ' + #DBName + ';SELECT ''' + #DBName + ''' AS DBName,
UserName = name, UserSID = sid from sysusers
WHERE issqluser = 1 AND
(sid IS NOT NULL AND sid <> 0x0) AND
(LEN(sid) <= 16) AND SUSER_SNAME(sid) IS NULL'
INSERT INTO #Results
EXEC(#SQL)
FETCH NEXT FROM cur into #DBName
END
CLOSE cur
DEALLOCATE cur
SELECT * FROM #Results
Thanks!
Thanks for the replies, I've created the below query based on the info given so far, this looks like it gives what I need?
select u.uid, u.name, u.sid, rm.role_principal_id as 'Role ID', dp1.name as 'Role'
from sys.sysusers u
left join sys.syslogins l on UPPER(u.sid) = UPPER(l.sid)
inner join sys.database_role_members rm on rm.member_principal_id = u.uid
left join sys.database_principals dp on dp.principal_id = rm.member_principal_id
left join sys.database_principals dp1 on dp1.principal_id = rm.role_principal_id
where u.uid > 4 and u.issqlrole = 0
and issqluser = 1
and l.name is null
order by u.name

It selects user membership.
select case when SUSER_SNAME( dp.sid ) is null then dp.name else SUSER_SNAME( dp.sid ) end 'dbUser',
dp2.name 'dbRole', dp.type_desc uDesc
from sys.database_principals dp left join sys.database_role_members dr
on dr.member_principal_id = dp.principal_id
left join sys.database_principals dp2 on dr.role_principal_id = dp2.principal_id
where dp.type_desc <> 'DATABASE_ROLE'
and case when SUSER_SNAME( dp.sid ) is null then dp.name else SUSER_SNAME( dp.sid ) end
not in ('sys', 'INFORMATION_SCHEMA', 'guest')
order by 1
I have noticed that your cursor selects orphaned SQL logins only. Do you need orphaned Windows logins? If yes, then check following query.
select u.name, *
from sys.sysusers u left join sys.syslogins l on UPPER(u.sid) = UPPER(l.sid)
where u.uid > 4 and u.issqlrole = 0
and l.name is null
order by u.name

Related

Issue with PK violation on insert

I have a scenario where almost all of the tables have issues with the PK value as follows. This results is a database error or the violation of the PK insert.
When using the DBCC CheckIdent it displays an inconsistency between the next value and the current one.
Can anyone have a reason for the mismatch happening on several tables?
Since this database is then replicate, I'm afraid this error will propagate across the environment.
I adapted this script to fix it, but really trying to figure out the root of the problem.
/** Version 3.0 **/
if object_id('tempdb..#temp') is not null
drop table #temp
;
with cte as (
SELECT
distinct
A.TABLE_CATALOG AS CATALOG,
A.TABLE_SCHEMA AS "SCHEMA",
A.TABLE_NAME AS "TABLE",
B.COLUMN_NAME AS "COLUMN",
IDENT_SEED (A.TABLE_NAME) AS Seed,
IDENT_INCR (A.TABLE_NAME) AS Increment,
IDENT_CURRENT (A.TABLE_NAME) AS Curr_Value
, DBPS.row_count AS NumberOfRows
FROM INFORMATION_SCHEMA.TABLES A
inner join INFORMATION_SCHEMA.COLUMNS B on b.TABLE_NAME = a.TABLE_NAME and b.TABLE_SCHEMA = a.TABLE_SCHEMA
inner join sys.identity_columns IC on OBJECT_NAME (IC.object_id) = a.TABLE_NAME
inner join sys.dm_db_partition_stats DBPS ON DBPS.object_id =IC.object_id
inner join sys.indexes as IDX ON DBPS.index_id =IDX.index_id
WHERE A.TABLE_CATALOG = B.TABLE_CATALOG AND
A.TABLE_SCHEMA = B.TABLE_SCHEMA AND
A.TABLE_NAME = B.TABLE_NAME AND
COLUMNPROPERTY (OBJECT_ID (B.TABLE_NAME), B.COLUMN_NAME, 'IsIdentity') = 1 AND
OBJECTPROPERTY (OBJECT_ID (A.TABLE_NAME), 'TableHasIdentity') = 1 AND
A.TABLE_TYPE = 'BASE TABLE'
)
select 'DBCC CHECKIDENT ('''+A.[SCHEMA]+'.'+a.[TABLE]+''', reseed)' command
, ROW_NUMBER() OVER(ORDER BY a.[SCHEMA], a.[TABLE] asc) AS ID
, A.Curr_Value
, a.[TABLE]
into #temp
from cte A
ORDER BY A.[SCHEMA], A.[TABLE]
declare #i int = 1, #count int = (select max(ID) from #temp)
declare #text varchar(max) = ''
select #COUNT= count(1) FROM #temp
WHILE #I <= #COUNT
BEGIN
SET #text = (SELECT command from #temp where ID=#I)
EXEC (#text + ';')
print #text
select Curr_Value OldValue, ident_current([TABLE]) FixValue, [TABLE] from #temp where ID=#I
SET #I = #I + 1
SET #text='';
END
go
maybe someone or something with enough permissions made a mistake by reseeding?
As simple as this:
create table testid (
id int not null identity (1,1) primary key,
data varchar (3)
)
insert into testid (data) values ('abc'),('cde')
DBCC CHECKIDENT ('testid', RESEED, 1)
insert into testid (data) values ('bad')

I am getting Dollar sign unterminated

I want to create a function like below which inserts data as per the input given. But I keep on getting an error about undetermined dollar sign.
CREATE OR REPLACE FUNCTION test_generate
(
ref REFCURSOR,
_id INTEGER
)
RETURNS refcursor AS $$
DECLARE
BEGIN
DROP TABLE IF EXISTS test_1;
CREATE TEMP TABLE test_1
(
id int,
request_id int,
code text
);
IF _id IS NULL THEN
INSERT INTO test_1
SELECT
rd.id,
r.id,
rd.code
FROM
test_2 r
INNER JOIN
raw_table rd
ON
rd.test_2_id = r.id
LEFT JOIN
observe_test o
ON
o.raw_table_id = rd.id
WHERE o.id IS NULL
AND COALESCE(rd.processed, 0) = 0;
ELSE
INSERT INTO test_1
SELECT
rd.id,
r.id,
rd.code
FROM
test_2 r
INNER JOIN
raw_table rd
ON rd.test_2_id = r.id
WHERE r.id = _id;
END IF;
DROP TABLE IF EXISTS tmp_test_2_error;
CREATE TEMP TABLE tmp_test_2_error
(
raw_table_id int,
test_2_id int,
error text,
record_num int
);
INSERT INTO tmp_test_2_error
(
raw_table_id,
test_2_id,
error,
record_num
)
SELECT DISTINCT
test_1.id,
test_1.test_2_id,
'Error found ' || test_1.code,
0
FROM
test_1
WHERE 1 = 1
AND data_origin.id IS NULL;
INSERT INTO tmp_test_2_error
SELECT DISTINCT
test_1.id,
test_1.test_2_id,
'Error found ' || test_1.code,
0
FROM
test_1
INNER JOIN
data_origin
ON
data_origin.code = test_1.code
WHERE dop.id IS NULL;
DROP table IF EXISTS test_latest;
CREATE TEMP TABLE test_latest AS SELECT * FROM observe_test WHERE 1 = 2;
INSERT INTO test_latest
(
raw_table_id,
series_id,
timestamp
)
SELECT
test_1.id,
ds.id AS series_id,
now()
FROM
test_1
INNER JOIN data_origin ON data_origin.code = test_1.code
LEFT JOIN
observe_test o ON o.raw_table_id = test_1.id
WHERE o.id IS NULL;
CREATE TABLE latest_observe_test as Select * from test_latest where 1=0;
INSERT INTO latest_observe_test
(
raw_table_id,
series_id,
timestamp,
time
)
SELECT
t.id,
ds.id AS series_id,
now(),
t.time
FROM
test_latest t
WHERE t.series_id IS DISTINCT FROM observe_test.series_id;
DELETE FROM test_2_error re
USING t
WHERE t.test_2_id = re.test_2_id;
INSERT INTO test_2_error (test_2_id, error, record_num)
SELECT DISTINCT test_2_id, error, record_num FROM tmp_test_2_error ORDER BY error;
UPDATE raw_table AS rd1
SET processed = case WHEN tre.raw_table_id IS null THEN 2 ELSE 1 END
FROM test_1 tr
LEFT JOIN
tmp_test_2_error tre ON tre.raw_table_id = tr.id
WHERE rd1.id = tr.id;
OPEN ref FOR
SELECT 1;
RETURN ref;
OPEN ref for
SELECT o.* from observe_test o
;
RETURN ref;
OPEN ref FOR
SELECT
rd.id,
ds.id AS series_id,
now() AS timestamp,
rd.time
FROM test_2 r
INNER JOIN raw_table rd ON rd.test_2_id = r.id
INNER JOIN data_origin ON data_origin.code = rd.code
WHERE o.id IS NULL AND r.id = _id;
RETURN ref;
END;
$$ LANGUAGE plpgsql VOLATILE COST 100;
I am not able to run this procedure.
Can you please help me where I have done wrong?
I am using squirrel and face the same question as you.
until I found that:
-- Note that if you want to create the function under Squirrel SQL,
-- you must go to Sessions->Session Properties
-- then SQL tab and change the Statement Separator from ';' to something else
-- (for intance //). Otherwise Squirrel SQL sends one piece to the server
-- that stops at the first encountered ';', and the server cannot make
-- sense of it. With the separator changed as suggested, you type everything
-- as above and end with
-- ...
-- end;
-- $$ language plpgsql
-- //
--
-- You can then restore the default separator, or use the new one for
-- all queries ...
--

Dynamic sql to select a specific value from a column using Joins

I am attempting to use dynamic sql to select a value based on a field. I have a table of field references I am using for the column names. What I am having troubles with is of course the dynamic sql. My return result is (SELECT ecoa_code FROM CRA_METRO2_BASE WHERE id = 568470) for example. But I really want it to run that select statement. Executing only returns the last row.
DECLARE #BaseCol VARCHAR(250)
SELECT
#BaseCol = '(SELECT ' + FR_base.field_name + ' FROM CRA_METRO2_BASE WHERE id = ' + CONVERT(VARCHAR(15), B.id) + ')'
FROM CRA_INNOVIS_AUDIT_ERROR_FIELDS E
LEFT JOIN CRA_METRO2_BASE B
ON B.id = E.base_id
LEFT JOIN CRA_METRO2_FIELD_REF FR_base
ON FR_base.id = E.base_field_ref
WHERE E.audit_id = #audit_id
EXEC(#BaseCol)
I am not sure I understand your premises correctly and without a mock-up...; so please take this answer with a grain of salt:)
DECLARE #sqlstring VARCHAR(MAX)
SELECT #sqlstring = 'SELECT ' + a.column_name + ' FROM ' + a.[Schema] + '.' + a.table_name
from (
SELECT TOP 1 T.object_id,OBJECT_SCHEMA_NAME(T.[object_id],DB_ID()) AS [Schema],
T.[name] AS [table_name], AC.[name] AS [column_name]
--,TY.[name] AS system_data_type
, AC.[max_length],
AC.[precision], AC.[scale], AC.[is_nullable], AC.[is_ansi_padded]
,AC.column_id
FROM sys.tables AS T
INNER JOIN sys.[all_columns] AC ON T.[object_id] = AC.[object_id]
) a
SELECT #sqlstring
EXEC(#sqlstring)
So I used my above query and now I am using a CTE to build my basic result list. And in my cte I create update statements which then are all put into a temp table.
I extract the update statements and execute them on the temp table. And walla, I have my results!
IF(OBJECT_ID('tempdb..#Temp') IS NOT NULL)
BEGIN
DROP TABLE #Temp
END
CREATE TABLE #Temp
(
usb_data VARCHAR(500),
cra_data VARCHAR(500)
);
WITH ErrorFieldsCTE(id, field, usb_data, cra_data, AUD, SOR, acceptable_variance, is_variance_known, is_reviewed)
AS(
SELECT
+ 'UPDATE #TEMP SET usb_data = (SELECT ' + FR_base.field_name +' FROM CRA_METRO2_BASE WHERE id = '+ CONVERT(VARCHAR(25), B.id) +' ) WHERE id = ' + CONVERT(VARCHAR(15), E.id) + ' ' [usb_data],
+ 'UPDATE #TEMP SET cra_data = (SELECT ' + FR_audit.field_name +' FROM CRA_INNOVIS_INBOUND_AUDIT_INFORMATION WHERE id = '+ CONVERT(VARCHAR(25), A.id) +') WHERE id = ' + CONVERT(VARCHAR(15), E.id) + ' ' [cra_data]
FROM CRA_INNOVIS_AUDIT_ERROR_FIELDS E
LEFT JOIN CRA_METRO2_BASE B
ON B.id = E.base_id
LEFT JOIN CRA_INNOVIS_INBOUND_AUDIT_INFORMATION A
ON A.id = E.audit_id
LEFT JOIN CRA_METRO2_FIELD_REF FR_audit
ON FR_audit.id = E.audit_field_ref
LEFT JOIN CRA_METRO2_FIELD_REF FR_base
ON FR_base.id = E.base_field_ref
WHERE E.audit_id = #audit_id
)
INSERT INTO #Temp
SELECT
id, field, usb_data, cra_data, AUD, SOR, acceptable_variance, is_variance_known, is_reviewed
FROM ErrorFieldsCTE
SELECT -- extract query
#usb_data += usb_data + '',
#cra_data += cra_data + ''
FROM #Temp
EXEC(#usb_data) -- updating temp table, selects usb-data
EXEC(#cra_data) -- updating temp table, selects cra-data
SELECT -- return to web
id, field, usb_data, cra_data, AUD, SOR, acceptable_variance, is_variance_known, is_reviewed
FROM #Temp
IF(OBJECT_ID('tempdb..#Temp') IS NOT NULL)
Begin
Drop Table #Temp
End

Concatenate Dynamic SQL Columns

I've got three tables; tblProducts and tblOption and tblOptionValue. (T-SQL)
I get all possible combinations of my product using the this query:
DECLARE #ProductId INT, #Query NVARCHAR(MAX), #ProductOptionGroupId INT
SET #ProductId = 69
SET #Query = ''
DECLARE CC CURSOR FOR
SELECT DISTINCT OptionID
FROM tblOption
WHERE ProductId = #ProductId
OPEN CC
FETCH NEXT FROM CC INTO #ProductOptionGroupId
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Query = #Query + '(SELECT DISTINCT tblOptionValue.Name FROM tblOptionValue INNER JOIN tblOption on tblOptionValue.OptionID = tblOption.OptionID WHERE tblOptionValue.OptionId='+CAST(#ProductOptionGroupId AS VARCHAR)+'AND tblOption.ProductId='+CAST(#ProductId AS VARCHAR)+
+') AS Table' + CAST(#ProductOptionGroupId AS VARCHAR)+' CROSS JOIN '
FETCH NEXT FROM CC INTO #ProductOptionGroupId
END
CLOSE CC
DEALLOCATE CC
SET #Query = 'SELECT * FROM ' + LEFT(#Query,LEN(#Query)-10)
PRINT #Query
EXEC sp_executesql #Query
Found here thanks to #Lamak
I've adapted it to my database but I need to:
A) Find a way to pull all the data back in one column instead of multiple columns
B) Name the tblOptionValue.Name column the same as the associated tblOption.Name field
Any thoughts on how I might achieve the above?
Many thanks
Update: I managed to achieve my goals, using the following query:
DECLARE #ProductId INT, #Query NVARCHAR(MAX), #ProductOptionGroupId INT, #cName VARCHAR(300)
SET #ProductId = 70
SET #Query = ''
DECLARE CC CURSOR FOR
SELECT DISTINCT OptionID
FROM tblOption
WHERE ProductId = #ProductId
OPEN CC
FETCH NEXT FROM CC INTO #ProductOptionGroupId
WHILE ##FETCH_STATUS = 0
BEGIN
set #cName = (SELECT Name FROM tblOption WHERE OptionID=#ProductOptionGroupId)
SET #Query = #Query + '(SELECT DISTINCT tblOptionValue.Name as '+#cName+' FROM tblOptionValue INNER JOIN tblOption on tblOptionValue.OptionID = tblOption.OptionID INNER JOIN tblProduct on tblOption.ProductID=tblProduct.ProductID WHERE tblOptionValue.OptionId='+CAST(#ProductOptionGroupId AS VARCHAR)+'AND tblOption.ProductId='+CAST(#ProductId AS VARCHAR)+
+') AS Table' + CAST(#ProductOptionGroupId AS VARCHAR)+' CROSS JOIN '
FETCH NEXT FROM CC INTO #ProductOptionGroupId
END
CLOSE CC
DEALLOCATE CC
SET #Query = 'SELECT t2.*, t1.* FROM (SELECT * FROM ' + LEFT(#Query,LEN(#Query)-10)
SET #Query = #Query + ') as t1,
(SELECT * FROM tblProduct WHERE ProductID=70) as t2'
PRINT #Query
EXEC sp_executesql #Query
Put the user's solution into an answer.
DECLARE #ProductId INT, #Query NVARCHAR(MAX), #ProductOptionGroupId INT, #cName VARCHAR(300)
SET #ProductId = 70
SET #Query = ''
DECLARE CC CURSOR FOR
SELECT DISTINCT OptionID
FROM tblOption
WHERE ProductId = #ProductId
OPEN CC
FETCH NEXT FROM CC INTO #ProductOptionGroupId
WHILE ##FETCH_STATUS = 0
BEGIN
set #cName = (SELECT Name FROM tblOption WHERE OptionID=#ProductOptionGroupId)
SET #Query = #Query + '(SELECT DISTINCT tblOptionValue.Name as '+#cName+' FROM tblOptionValue INNER JOIN tblOption on tblOptionValue.OptionID = tblOption.OptionID INNER JOIN tblProduct on tblOption.ProductID=tblProduct.ProductID WHERE tblOptionValue.OptionId='+CAST(#ProductOptionGroupId AS VARCHAR)+'AND tblOption.ProductId='+CAST(#ProductId AS VARCHAR)+
+') AS Table' + CAST(#ProductOptionGroupId AS VARCHAR)+' CROSS JOIN '
FETCH NEXT FROM CC INTO #ProductOptionGroupId
END
CLOSE CC
DEALLOCATE CC
SET #Query = 'SELECT t2.*, t1.* FROM (SELECT * FROM ' + LEFT(#Query,LEN(#Query)-10)
SET #Query = #Query + ') as t1,
(SELECT * FROM tblProduct WHERE ProductID=70) as t2'
PRINT #Query
EXEC sp_executesql #Query

Establishing Upper / Lower Bound in T-SQL Procedure

I am trying to establish upper / lower bound in my stored procedure
below and am having some problems at the end (I am getting no results
where, without the temp table inner join i get the expected results).
I need some help where I am trying to join the columns in my temp table #PageIndexForUsers
to the rest of my join statement and I am mucking something up with
this statement:
INNER JOIN
#PageIndexForUsers ON ( dbo.aspnet_Users.UserId =
#PageIndexForUsers.UserId AND #PageIndexForUsers.IndexId >= #PageLowerBound AND
#PageIndexForUsers.IndexId <= #PageUpperBound )
I could use feedback at this point - and, any advice on how to improve
my procedure's logic (if you see anything else that needs improvement) is also appreciated.
Thanks in advance...
ALTER PROCEDURE dbo.wb_Membership_GetAllUsers
#ApplicationName nvarchar(256),
#sortOrderId smallint = 0,
#PageIndex int,
#PageSize int
AS
BEGIN
DECLARE #ApplicationId uniqueidentifier
SELECT #ApplicationId = NULL
SELECT #ApplicationId = ApplicationId FROM dbo.aspnet_Applications WHERE LOWER(#ApplicationName) = LoweredApplicationName
IF (#ApplicationId IS NULL)
RETURN 0
-- Set the page bounds
DECLARE #PageLowerBound int
DECLARE #PageUpperBound int
DECLARE #TotalRecords int
SET #PageLowerBound = #PageSize * #PageIndex
SET #PageUpperBound = #PageSize - 1 + #PageLowerBound
BEGIN TRY
-- Create a temp table TO store the select results
CREATE TABLE #PageIndexForUsers
(
IndexId int IDENTITY (0, 1) NOT NULL,
UserId uniqueidentifier
)
-- Insert into our temp table
INSERT INTO #PageIndexForUsers (UserId)
SELECT u.UserId
FROM dbo.aspnet_Membership m, dbo.aspnet_Users u
WHERE u.ApplicationId = #ApplicationId AND u.UserId = m.UserId
ORDER BY u.UserName
SELECT #TotalRecords = ##ROWCOUNT
SELECT dbo.wb_Profiles.profileid, dbo.wb_ProfileData.firstname, dbo.wb_ProfileData.lastname, dbo.wb_Email.emailaddress, dbo.wb_Email.isconfirmed, dbo.wb_Email.emaildomain, dbo.wb_Address.streetname, dbo.wb_Address.cityorprovince, dbo.wb_Address.state, dbo.wb_Address.postalorzip, dbo.wb_Address.country, dbo.wb_ProfileAddress.addresstype,dbo.wb_ProfileData.birthday, dbo.wb_ProfileData.gender, dbo.wb_Session.sessionid, dbo.wb_Session.lastactivitydate, dbo.aspnet_Membership.userid, dbo.aspnet_Membership.password, dbo.aspnet_Membership.passwordquestion, dbo.aspnet_Membership.passwordanswer, dbo.aspnet_Membership.createdate
FROM dbo.wb_Profiles
INNER JOIN dbo.wb_ProfileAddress
ON
(
dbo.wb_Profiles.profileid = dbo.wb_ProfileAddress.profileid
AND dbo.wb_ProfileAddress.addresstype = 'home'
)
INNER JOIN dbo.wb_Address
ON dbo.wb_ProfileAddress.addressid = dbo.wb_Address.addressid
INNER JOIN dbo.wb_ProfileData
ON dbo.wb_Profiles.profileid = dbo.wb_ProfileData.profileid
INNER JOIN dbo.wb_Email
ON
(
dbo.wb_Profiles.profileid = dbo.wb_Email.profileid
AND dbo.wb_Email.isprimary = 1
)
INNER JOIN dbo.wb_Session
ON dbo.wb_Profiles.profileid = dbo.wb_Session.profileid
INNER JOIN
dbo.aspnet_Membership
ON dbo.wb_Profiles.userid = dbo.aspnet_Membership.userid
INNER JOIN
dbo.aspnet_Users
ON dbo.aspnet_Membership.UserId = dbo.aspnet_Users.UserId
INNER JOIN
dbo.aspnet_Applications
ON dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
INNER JOIN
#PageIndexForUsers ON ( dbo.aspnet_Users.UserId =
#PageIndexForUsers.UserId AND #PageIndexForUsers.IndexId >= #PageLowerBound AND
#PageIndexForUsers.IndexId <= #PageUpperBound )
ORDER BY CASE #sortOrderId
WHEN 1 THEN dbo.wb_ProfileData.lastname
WHEN 2 THEN dbo.wb_Profiles.username
WHEN 3 THEN dbo.wb_Address.postalorzip
WHEN 4 THEN dbo.wb_Address.state
END
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 ROLLBACK TRAN
EXEC wb_ErrorHandler
RETURN 55555
END CATCH
RETURN #TotalRecords
END
GO
You don't have enough rows in #PageIndexForUsers, no?
If #PageSize = 50 and you want #PageIndex 2, then you are looking for rows 100 to 149 from #PageIndexForUsers. Do you have this many rows?
The row filter should be applied over the larger dataset that starts FROM dbo.wb_Profiles