Is there a way to find a particular user account in a database on a SQL Server?
Typically you would add an account to the SQL Server, at which point you can also map the user to multiple databases on that server. As long as no one does anything bad, you can return to the account properties on the server as see the databases the account was mapped to.
However, this linkage can be easily broken, where an account exists in a database, but it does not show up as mapped to that database at the server level. Also, you cannot create an account on the server if it already exists in one of the databases, this is the situation I'm in.
There are 100's of databases and I need to find the one that this users account is in. As far as I know sys.database_principals us unique to each database. Is it possible to do a cross database search for an account and return the database(s) that it exists in?
Here are some helper queries.
declare #returnValue int
EXEC #returnValue = sp_change_users_login 'Update_One', 'SXAUtil', 'SXAUtil'
print '/#returnValue/'
print #returnValue
print ''
select * from master..syslogins where name='MyUser001'
select * from [MyDatabase001]..sysusers where name='MyUser001'
select 1 as 'Match??' , mastSysLogin.sid as mastSysLogin_Sid, localSysLogin.sid as localSysLogin_Sid, mastSysLogin.name as mastSysLogin_Name , localSysLogin.name as localSysLogin_Name from master..syslogins mastSysLogin join [MyDatabase001]..sysusers localSysLogin on mastSysLogin.sid = localSysLogin.sid
where mastSysLogin.name='MyUser001'
go
This procedure is being deprecated I think, but researching it will show some "missing link" informaiton.
Use MyDatabase001
GO
declare #returnValue int
EXEC #returnValue = sp_change_users_login 'Update_One', 'MyUser001', 'MyUser001'
print '/#returnValue/'
print #returnValue
print ''
Below is a script I wrote to add users to logins and as dbusers and map to some roles.
It uses SQLCMD Mode. But it is a "over the years" effort as I tried to write code to create users , and it wouldn't throw errors if the user was already added.
/*
--SqlCmd Notes:
--Remove comments and space between ":" and "setvar" to run in sqlcmd mode.
--!!! Checked in code MUST *recomment out* the setvars below !!! (Putting a space between the ":" and the "setvar" is sufficient)
-- (This is not preferred behavior, the issue has been reported at http://connect.microsoft.com/SQLServer/feedback/details/382007/in-sqlcmd-scripts-setvar-should-have-a-lower-precedence-than-command-line-variable-assignments )
: setvar ErrorOutputFileFromCommandLine "c:\wuwutemp\sqlcommmanderrorfile.txt"
: setvar DBNAME "MyDatabaseName"
: setvar DBUSERNAME "MyDomain\someDomainUserThatExists"
*/
Use [$(DBNAME)]
GO
:Error $(ErrorOutputFileFromCommandLine)
declare #databaseName varchar(64)
select #databaseName = db_name()
print '/#databaseName/'
print #databaseName
print ''
set nocount on
declare #CONST_DB_DATAREADER_ROLE varchar(64)
select #CONST_DB_DATAREADER_ROLE = 'db_datareader'
declare #CONST_DB_BACKUPOPERATOR_ROLE varchar(64)
select #CONST_DB_BACKUPOPERATOR_ROLE = 'db_backupoperator'
declare #UserNameHolder table ( IdentityID int identity(101,1) , DatabaseName varchar(128) , LoginName varchar(256) , MassagedLoginName varchar(264) , RoleName varchar(64) not null , AlreadyProcessed bit default 0 not null )
INSERT INTO #UserNameHolder ( DatabaseName , LoginName , RoleName ) values ( '$(DBNAME)' , '$(DBUSERNAME)' , #CONST_DB_DATAREADER_ROLE )
--INSERT INTO #UserNameHolder ( DatabaseName , LoginName , RoleName ) values ( '$(DBNAME)' , '$(DBUSERNAME)' , #CONST_DB_BACKUPOPERATOR_ROLE )
/* Below this line is "common logic code" */
Update #UserNameHolder Set MassagedLoginName = LoginName
/*
sp_grantlogin does NOT like brackets around a domain/user
example : EXEC sp_grantlogin #loginame = N'[MyDomain\MyUser]'
The "massaging" below is a work around to this issue
*/
Update #UserNameHolder Set MassagedLoginName = RIGHT(MassagedLoginName , LEN(MassagedLoginName) -1 ) where LEN(MassagedLoginName)>0 AND LEFT( MassagedLoginName,1)='['
Update #UserNameHolder Set MassagedLoginName = LEFT( MassagedLoginName , LEN(MassagedLoginName) -1 ) where LEN(MassagedLoginName)>0 AND RIGHT(MassagedLoginName,1)=']'
/* Use a iffy rule to figure out NT Names */
--Update #UserNameHolder Set IsNTName = 1 where LEN(LoginName)>0 AND LEFT( LoginName,1)='[' AND RIGHT(LoginName,1)=']'
-- public is built in, do not process it
Update #UserNameHolder Set AlreadyProcessed = 1 where UPPER(LoginName) = UPPER('public')
select * from #UserNameHolder
declare #CurrentIdentityID int
declare #CurrentLoginName varchar(256)
declare #CurrentMassagedLoginName varchar(256)
declare #CurrentDatabaseName varchar(64)
--declare #CurrentIsNTName bit
declare #CurrentRoleName varchar(64)
declare #sp_grantdbaccess_return_value_total int
select #sp_grantdbaccess_return_value_total = 0
declare #sp_addrolemember_return_value_total int
select #sp_addrolemember_return_value_total = 0
while exists (select null from #UserNameHolder where AlreadyProcessed = 0)
begin
select #CurrentIdentityID = (select top 1 IdentityID from #UserNameHolder where AlreadyProcessed = 0)
print '#CurrentIdentityID'
print #CurrentIdentityID
print ''
select #CurrentLoginName = ( select top 1 LoginName from #UserNameHolder where IdentityID = #CurrentIdentityID )
select #CurrentMassagedLoginName = ( select top 1 MassagedLoginName from #UserNameHolder where IdentityID = #CurrentIdentityID )
select #CurrentDatabaseName = ( select top 1 DatabaseName from #UserNameHolder where IdentityID = #CurrentIdentityID )
--select #CurrentIsNTName = ( select top 1 IsNTName from #UserNameHolder where IdentityID = #CurrentIdentityID )
select #CurrentRoleName = ( select top 1 RoleName from #UserNameHolder where IdentityID = #CurrentIdentityID )
print '#CurrentLoginName'
print #CurrentLoginName
print ''
print '#CurrentMassagedLoginName'
print #CurrentMassagedLoginName
print ''
print '#CurrentDatabaseName'
print #CurrentDatabaseName
print ''
--print '#CurrentIsNTName'
--print #CurrentIsNTName
--print ''
print '#CurrentRoleName'
print #CurrentRoleName
print ''
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
-- select name, loginname from master.dbo.syslogins where loginname = #currentLoginName and isntname = 1)
if not exists (select null from master.dbo.syslogins where UPPER(loginname) = UPPER(#CurrentLoginName) ) -- and isntname = 1)
begin
print 'About to execute sp_grantlogin for user:'
print #CurrentMassagedLoginName
EXEC sp_grantlogin #loginame = #CurrentMassagedLoginName
print ''
print ''
print 'About to execute sp_defaultdb for user:'
print #CurrentMassagedLoginName
EXEC sp_defaultdb #loginame = #CurrentMassagedLoginName , #defdb = #CurrentDatabaseName
print ''
print ''
end
else
begin
print 'NOT EXECUTED : sp_grantlogin'
print 'NOT EXECUTED : sp_defaultdb'
end
end
----------------------------------------
declare #sp_grantdbaccess_return_value int
declare #sp_change_users_login_return_value int
declare #needToRunThisIteration bit
select #needToRunThisIteration = 0
-- declare #currentLoginName varchar(64)
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
if not exists
(
select * from master.dbo.syslogins ml inner join dbo.sysusers
su on ml.sid = su.sid where
su.uid < 6382
and
UPPER(ml.name) = UPPER(#CurrentMassagedLoginName)
)
begin
if not exists
(
/* NOTE, this database name variable must be updated if copying/pasting 'common logic code' between database deployments (NEED_TO_REPLACE_A_VALUE) */
select * from master.dbo.syslogins ml Where
UPPER(ml.name) = UPPER(#CurrentMassagedLoginName)
and UPPER(ml.dbname) = UPPER('$(DBNAME)')
)
begin
select #needToRunThisIteration = 1
end
end
if not exists
(
/* NOTE, this database name variable must be updated if copying/pasting 'common logic code' between database deployments (NEED_TO_REPLACE_A_VALUE) */
select * FROM [$(DBNAME)]..sysusers su Where
UPPER(su.name) = UPPER(#CurrentMassagedLoginName)
)
begin
select #needToRunThisIteration = 1
end
/*
Debug
select dbname , loginname , * from master.dbo.syslogins ml where dbname != 'master' order by 1 , 2
select * FROM TPA2Report..sysusers su
*/
declare #stringNameMatchesButNotSid bit
select #stringNameMatchesButNotSid = 0
IF EXISTS (
SELECT dbUsers.name as NameToFix , *
FROM sys.sysusers dbUsers
join sys.syslogins sqlServerLogins on UPPER(dbUsers.name) = UPPER(sqlServerLogins.name)
WHERE dbUsers.sid != sqlServerLogins.sid
and UPPER(dbUsers.name) = UPPER(#CurrentMassagedLoginName)
)
begin
select #stringNameMatchesButNotSid = 1
end
if (#needToRunThisIteration!=0)
begin
if #stringNameMatchesButNotSid = 0
begin
print 'About to execute sp_grantdbaccess for user:'
print #CurrentMassagedLoginName
exec #sp_grantdbaccess_return_value = sp_grantdbaccess #CurrentMassagedLoginName
print ''
print '#sp_grantdbaccess_return_value'
print #sp_grantdbaccess_return_value
print ''
select #sp_grantdbaccess_return_value_total = #sp_grantdbaccess_return_value_total + #sp_grantdbaccess_return_value
end
else
begin
/* There is a mismatched "sid" issue, but with the same names. This will address the issue. */
print 'About to execute sp_change_users_login for user:'
print #CurrentMassagedLoginName
EXEC #sp_change_users_login_return_value = sp_change_users_login #Action='update_one', #UserNamePattern=#CurrentMassagedLoginName,#LoginName=#CurrentMassagedLoginName;
print ''
print '#sp_change_users_login_return_value'
print #sp_change_users_login_return_value
print ''
end
end
end
-------------------------------------------------------
declare #sp_addrolemember_return_value int
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
if not exists
(
SELECT null --, role_principal_id, member_principal_id, princ1.name AS
role_name, princ2.name As member_name
FROM sys.database_role_members AS S LEFT JOIN sys.database_principals AS
princ1 ON S.role_principal_id = princ1.principal_id AND princ1.type = 'R'
LEFT JOIN sys.database_principals AS princ2 ON S.member_principal_id =
princ2.principal_id AND princ2.type IN ('S', 'U')
WHERE princ1.name = #CurrentRoleName and UPPER(princ2.name) = UPPER(#CurrentMassagedLoginName)
)
begin
print 'About to execute sp_grantdbaccess for user:'
print #CurrentMassagedLoginName
print 'For the role:'
print #CurrentRoleName
exec #sp_addrolemember_return_value = sp_addrolemember #CurrentRoleName, #CurrentMassagedLoginName
print ''
print '#sp_addrolemember_return_value'
print #sp_addrolemember_return_value
print ''
select #sp_addrolemember_return_value_total = #sp_addrolemember_return_value_total + #sp_addrolemember_return_value
end
end
Update #UserNameHolder Set AlreadyProcessed = 1 Where IdentityID = #CurrentIdentityID
end
print '/#sp_grantdbaccess_return_value_total/'
print #sp_grantdbaccess_return_value_total
print '/#sp_addrolemember_return_value_total/'
print #sp_addrolemember_return_value_total
GO
Related
This trigger was not written by me or used with a stored proc original I modified it for my use. The problem to me appears to be one of permissions when the table is manually updated or inserted inSQL Server Management Studio the trigger works perfectly. When the Trigger is updated or inserted by a Stored Proc ran via an ODBC connection it does not modify the table and the Trigger does not work. If the trigger is disabled the stored Proc works as expected. So the error appers to be some form of permission error. Here is the trigger. (Using 2012)
Thanks In Advance
Donald S. Bossen
USE [JBI]
GO
/****** Object: Trigger [dbo].[send_ship_exec_info_to_p21] Script Date: 8/29/2018 3:22:26 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[send_ship_exec_info_to_p21] ON [dbo].[ship_exec]
FOR INSERT, UPDATE
AS
declare #pick_ticket_no varchar(50)
declare #tracking_no varchar(50)
declare #pickup_date varchar(50)
declare #carrier_id varchar(50)
declare #package_count varchar(50)
declare #delete_flag varchar(50)
declare #package_weight varchar(50)
declare #package_charge decimal(9,4)
declare #total_shipment_charge decimal(19,4)
declare #carrier_name varchar(50)
declare #customer_freight_charge decimal(9,4)
declare #saturday_delivery varchar(50)
declare #transaction_type varchar(50)
declare #billing_option varchar(3)
select
#pick_ticket_no = i.pick_ticket_no,
#tracking_no = i.tracking_no,
#pickup_date = i.pickup_date,--left(i.pickup_date,8),
#carrier_id = i.service_type,
#package_count = i.package_count,
#delete_flag = i.delete_flag,
#package_weight = i.package_weight,
#package_charge = i.package_charge,
#total_shipment_charge = i.total_shipping_and_handling_charge,
#saturday_delivery = i.saturday_delivery,
#transaction_type = i.transaction_type,
#billing_option = i.billing_option
from inserted i
if #transaction_type = 'Inv Return'
begin
declare #document_link_uid int
declare #document_link_area_uid int
declare #link_name varchar(255)
declare #link_path varchar(4099)
set #link_name = 'UPS shipment ' + cast(#pick_ticket_no as varchar(40)) + ': ' + #tracking_no
set #link_path = 'http://wwwapps.ups.com/WebTracking/processInputRequest?HTMLVersion=5.0&sort_by=status&term_warn=yes&tracknums_displayed=5&TypeOfInquiryNumber=T&loc=en_US&InquiryNumber1=' + #tracking_no + '&InquiryNumber2=&InquiryNumber3=&InquiryNumber4=&InquiryNumber5=&AgreeToTermsAndConditions=yes&track.x=28&track.y=2'
if #delete_flag = 'Y'
begin
update
PROPHET21.dbo.document_link
set
row_status_flag = '700'
,date_last_modified = getdate()
,last_maintained_by = 'Ship Exec Delete Flag'
where
key1_cd = 'return_number'
and key1_value = #pick_ticket_no
and link_path like '%' + #tracking_no + '%'
end
if #delete_flag = 'N'
begin
if not exists(select document_link_uid from PROPHET21.dbo.document_link where link_path like '%' + #tracking_no + '%')
begin
exec #document_link_uid = PROPHET21.dbo.p21_get_counter 'document_link', 1
INSERT INTO
PROPHET21.dbo.document_link
(
document_link_uid
,source_area_cd
,key1_cd
,key1_value
,link_name
,link_path
,row_status_flag
,date_created
,created_by
,date_last_modified
,last_maintained_by
,outside_use_flag
,mandatory_flag
)
VALUES
(
#document_link_uid
,1312
,'return_number'
,#pick_ticket_no
,#link_name
,#link_path
,704
,getdate()
,'SHIP EXEC'
,getdate()
,'SHIP EXEC'
,'N'
,'N'
)
exec #document_link_area_uid = PROPHET21.dbo.p21_get_counter 'document_link_area', 1
INSERT INTO
PROPHET21.dbo.document_link_area
(
document_link_area_uid
,document_link_uid
,display_area_cd
,row_status_flag
,date_created
,created_by
,date_last_modified
,last_maintained_by
)
VALUES
(
#document_link_area_uid
,#document_link_uid
,1312
,704
,getdate()
,'SHIP EXEC'
,getdate()
,'SHIP EXEC'
)
end
end
end
if #transaction_type <> 'SWS' or not exists(select oe_pick_ticket.pick_ticket_no from PROPHET21.dbo.oe_pick_ticket oe_pick_ticket where oe_pick_ticket.pick_ticket_no = #pick_ticket_no)
return
if #transaction_type = 'SWS' and exists(select oe_pick_ticket.pick_ticket_no from PROPHET21.dbo.oe_pick_ticket oe_pick_ticket where oe_pick_ticket.pick_ticket_no = #pick_ticket_no)
begin
if (#delete_flag = 'Y')
begin
declare #invoiced_already varchar (50)
select #invoiced_already = oe_pick_ticket.invoice_no
from PROPHET21.dbo.oe_pick_ticket oe_pick_ticket
where pick_ticket_no = #pick_ticket_no
if(#invoiced_already is null)
begin
update PROPHET21.dbo.clippership_return_10004
set delete_flag = 'Y'
where tracking_no = #tracking_no
update PROPHET21.dbo.oe_pick_ticket
set freight_out = 0, date_last_modified = getdate(), last_maintained_by = 'Ship Exec void package'
where pick_ticket_no = #pick_ticket_no
end
return
end
if (#delete_flag = 'N')--#tracking_no like '1z%' and
Begin
declare #customer_pays_outgoing_freight char(1)
select
#customer_pays_outgoing_freight = freight_code.outgoing_freight
from
PROPHET21.dbo.oe_pick_ticket oe_pick_ticket
inner join PROPHET21.dbo.freight_code freight_code on oe_pick_ticket.freight_code_uid = freight_code.freight_code_uid and oe_pick_ticket.company_id = freight_code.company_id
where
oe_pick_ticket.pick_ticket_no = #pick_ticket_no
select
#carrier_name = carrier.name
from
PROPHET21.dbo.address carrier
where
carrier.id = #carrier_id
select #customer_freight_charge =
cast(case
when #billing_option in ('REC', 'TP', 'CB') then 0
when coalesce(#customer_pays_outgoing_freight, 'Y') = 'N' then 0
else ((#total_shipment_charge) / #package_count)
end as decimal(19,2))
update PROPHET21.dbo.oe_pick_ticket
set freight_out = isnull(freight_out, 0) + isnull(#customer_freight_charge, 0),
carrier_id = #carrier_id,
tracking_no = #tracking_no
where pick_ticket_no = #pick_ticket_no
insert into PROPHET21.dbo.clippership_return_10004
(pick_ticket_no,
tracking_no,
package_weight,
order_count,
shipped_date,
carrier_name,
total_charge,
processed_flag,
delete_flag,
date_created,
date_last_modified,
last_maintained_by,
line_number)
values
(#pick_ticket_no,
#tracking_no,
#package_weight,
#package_count,
#pickup_date,
#carrier_name,
#customer_freight_charge,
'N',
'N',
getdate(),
getdate(),
'SHIP EXEC',
0)
end
return
End
i want to add some messages in my stored procedure according to if else condition how can i do that. the issue is i have three tables team , account and user. i want to delete the teamA in team table only on the condition if there is not any account and user is related to that team. i have the stored procedure which is working fine but i want to check the condition and want to add some custom messages using if else . please help here is my code.
Create PROCEDURE sp_DeleteTeam
#pTeamId int
AS
BEGIN
SET NOCOUNT ON;
update t
set t.Deleted =1
from Team t
where t.TeamId = #pTeamId
And Not Exists (Select 1 from [User] where TeamId = #pTeamId)
And Not Exists (Select 1 from Account where TeamId = #pTeamId)
END
Don't use the prefix sp_ for user stored procedures as that is reserved for system procs.
Below is an example that returns the message using RAISERROR. A severity of 11 or higher as in this example will raise an exception in the application. Severity of 10 or lower will generate an informational message.
CREATE PROCEDURE usp_DeleteTeam #pTeamId int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Message varchar(2047);
UPDATE t
SET t.Deleted = 1
FROM Team t
WHERE t.TeamId = #pTeamId
AND NOT EXISTS ( SELECT 1
FROM [User]
WHERE TeamId = #pTeamId )
AND NOT EXISTS ( SELECT 1
FROM Account
WHERE TeamId = #pTeamId );
IF ##ROWCOUNT = 0
BEGIN
IF NOT EXISTS ( SELECT *
FROM Team
WHERE TeamId = #pTeamId )
BEGIN
SET #Message = 'does not exist in Team table';
END;
IF EXISTS ( SELECT *
FROM [User]
WHERE TeamId = #pTeamId )
BEGIN
SET #Message = COALESCE(#Message + ', ', '')
+ 'already exists in User table';
END;
IF EXISTS ( SELECT *
FROM Account
WHERE TeamId = #pTeamId )
BEGIN
SET #Message = COALESCE(#Message + ', ', '')
+ 'already exists in Account table';
END;
SET #Message = 'Team %d: ' + #Message
RAISERROR(#Message, 11, 0, #pTeamId);
END;
END;
Use the below SP to use print or select message.
Create PROCEDURE sp_DeleteTeam
#pTeamId int
AS
BEGIN
SET NOCOUNT ON;
IF ((NOT EXISTS (SELECT TOP 1 FROM [User] WHERE TeamId = #pTeamId)) AND (Not EXISTS (SELECT TOP 1 FROM Account WHERE TeamId = #pTeamId)))
BEGIN
UPDATE T
SET T.Deleted = 1
FROM Team t
WHERE T.TeamId = #pTeamId
SELECT 'Not exist - Table updated' AS Message
--PRINT 'Not exist - Table updated'
END
ELSE
BEGIN
SELECT 'Already exist - Table not updated.' AS Message
--PRINT 'Already exist - Table not updated.'
END
END
As far as I understood you just want to see if it executed sucessfully. If the stored Procedure is being called In some Applciation, At the end, Give a select statement as
SELECT 'Your message' AS Message
Then in application store the result in Dataset and retrieve your message,
If you are not using it in any application, then simply use
print 'your message'
OR may be try to be more specific and elaborate you problem a bit clearly.
Can i write the following query in other way?
ALTER PROC Proc_AssetManagement_SubscriptionCheck #IMEINumber NVARCHAR(100)
,#PhoneNo NVARCHAR(200)
,#SIMNo NVARCHAR(100)
,#Id INT
,#Message NVARCHAR(MAX) OUTPUT
AS
BEGIN
DECLARE #SimMessage NVARCHAR(200) = ''
DECLARE #PhoneMessage NVARCHAR(200) = ''
SET #Message = ''
SELECT #Message = (
CASE
WHEN COUNT(IMEINumber) > 0
THEN ('IMEI Already Exists\n')
ELSE ' '
END
)
FROM tblAssetSubscriptionDetails
WHERE AssetMgmtId <> #Id
AND (IMEINumber = #IMEINumber)
SELECT #PhoneMessage = (
CASE
WHEN COUNT(PhoneNo) > 0
THEN ('PhoneNo Already Exists\n')
ELSE ' '
END
)
FROM tblAssetSubscriptionDetails
WHERE AssetMgmtId <> #Id
AND (PhoneNo = #PhoneNo)
SELECT #SimMessage = (
CASE
WHEN COUNT(SimNo) > 0
THEN ('SimNo Already Exists')
ELSE ' '
END
)
FROM tblAssetSubscriptionDetails
WHERE AssetMgmtId <> #Id
AND (SIMNo = #SIMNo)
SET #Message = #Message + '' + #PhoneMessage + '' + #SimMessage
END
I want to reduce the number of queries and want to get the message in single query rather then 3 different queries. Can i do it? If so then how?
My purpose is that I want to get a message formed like this.
If IMEINumber is found in the table then it will show IMEI number already exists.
If SIm No is found in the table along with IMEINumber then it will show IMEI number already exists\nSim No already exists and so on...
Would this fit your need ? (Using a CTE: http://msdn.microsoft.com/en-us/library/ms175972.aspx. I wrote it partially in Notepad++ so I hope there aren't syntax error.)
The CTE tASD (stands for tblAssetSubscriptionDetails) gathers only the rows that will be useful. EXISTS should normally be better than Count() > 0 since it doesn't actually need to count everything.
WITH tASD(AssetMgmtId, IMEINumber, PhoneNo, SIMNo)
AS
(
SELECT AssetMgmtId, IMEINumber, PhoneNo, SIMNo
FROM tblAssetSubscriptionDetails
WHERE AssetMgmtId <> #Id
AND
(
IMEINumber = #IMEINumber
OR PhoneNo = #PhoneNo
OR SIMNo = #SIMNo
)
)
SELECT #Message = (
CASE
WHEN EXISTS (SELECT null FROM tASD WHERE IMEINumber = #IMEINumber)
THEN ('IMEI Already Exists\n')
ELSE ''
END
)
+
CASE
WHEN EXISTS (SELECT null FROM tASD WHERE PhoneNo = #PhoneNo)
THEN ('PhoneNo Already Exists\n')
ELSE ''
END
)
+
CASE
WHEN EXISTS (SELECT null FROM tASD WHERE SIMNo = #SIMNo)
THEN ('SimNo Already Exists')
ELSE ''
END
)
I have a stored procedure below. In it is a nested loop. Instead of using FETCH_STATUS I want to use something else to mark my cursor as being finished, so that I can do a nested loop. But it's never picking up #Client_ID in the cursor and I don't know why.
ALTER PROCEDURE [dbo].[Import_Agent_Client_Bucket_2010]
AS
BEGIN
-- Loop Through Each Agent, Create a Bucket, Add their Clients to the Bucket
DECLARE Agent_Cursor CURSOR FOR
SELECT TOP 10 Agent_GUID, Agent_ID
FROM realforms_2011.dbo.Agent
DECLARE #Agent_GUID uniqueidentifier
DECLARE #Agent_ID int
OPEN Agent_Cursor;
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
DECLARE #MaxAgentCount int
SELECT #MaxAgentCount = COUNT(Agent_ID)
FROM Agent
DECLARE #AgentCounter int
SET #AgentCounter = 0
WHILE (1 < 2)
BEGIN
PRINT 'Agent Counter:'
PRINT #AgentCounter
SET #AgentCounter = #AgentCounter + 1
-- Create a bucket for each agent
DECLARE #cbPKTable TABLE (cbPK UNIQUEIDENTIFIER, cbID int)
INSERT INTO realforms_2011.dbo.Client_Bucket ([Description] ) OUTPUT inserted.Client_Bucket_GUID, inserted.Client_Bucket_ID INTO #cbPKTable
SELECT ISNULL(a.First_Name, ' ') + ' ' + ISNULL(a.Last_Name, ' ') + '''s Clients'
FROM realforms_2011.dbo.Agent a
WHERE Agent_GUID = #Agent_GUID
DECLARE #Client_Bucket_GUID uniqueidentifier
SELECT #Client_Bucket_GUID = cbPK FROM #cbPKTable
PRINT 'Client Bucket GUID Inserted:'
PRINT #Client_Bucket_GUID
DECLARE #Client_Bucket_ID int
SELECT #Client_Bucket_ID = cbID FROM #cbPKTable
INSERT INTO realforms_2011.dbo.Agent_Client_Bucket (Agent_GUID, Agent_ID, Client_Bucket_GUID, Client_Bucket_ID)
VALUES (#Agent_GUID, #Agent_ID, #Client_Bucket_GUID, #Client_Bucket_ID)
DECLARE #Client_GUID uniqueidentifier
DECLARE #Client_ID int
-- Get clients from the server (2010)
DECLARE Client_Cursor CURSOR FOR
SELECT C.Client_ID
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID
ORDER BY C.Client_ID ASC
DECLARE #MaxClientCreateDate datetime
SELECT #MaxClientCreateDate = MAX(Create_Date)
FROM realforms.dbo.Client C
PRINT 'Max Create Date:'
PRINT #MaxClientCreateDate
DECLARE #ClientCreateDate datetime
SET #ClientCreateDate = CAST('01-01-2000' AS datetime)
OPEN Client_Cursor;
FETCH NEXT FROM Client_Cursor
INTO #Client_ID
-- loop through each 2010 client
WHILE (1 < 2)
BEGIN
DECLARE #myNewPKTable TABLE (myNewPK UNIQUEIDENTIFIER)
BEGIN TRY
PRINT 'Client ID:'
PRINT #Client_ID
PRINT 'Agent ID:'
PRINT #Agent_ID
INSERT INTO realforms_2011.dbo.Client (Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,[Year],IsFavorite) OUTPUT inserted.Client_GUID INTO #myNewPKTable
SELECT c.Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,2010,0
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID AND C.Client_ID = #Client_ID
SELECT #Client_GUID = myNewPK FROM #myNewPKTable
PRINT 'Client GUID Inserted: '
PRINT #Client_GUID
INSERT INTO realforms_2011.dbo.Client_Bucket_Client (Client_Bucket_GUID, Client_GUID, Client_ID, Client_Bucket_ID, [Year])
VALUES (#Client_Bucket_GUID, #Client_GUID, #Client_ID, #Client_Bucket_ID, 2010)
PRINT 'Client Bucket GUID: '
PRINT #Client_Bucket_GUID
PRINT 'Client ID Inserted: '
PRINT #Client_ID
SELECT #ClientCreateDate = CAST(Create_Date as datetime)
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID AND C.Client_ID = #Client_ID
PRINT #ClientCreateDate
END TRY
BEGIN CATCH
PRINT 'Error:'
PRINT ERROR_MESSAGE()
PRINT 'Last Client GUID Inserted: '
PRINT #Client_GUID
PRINT 'Last Client ID: '
PRINT #Client_ID
END CATCH
IF ##ERROR != 0 GOTO ERR_HANDLER
IF (#ClientCreateDate >= #MaxClientCreateDate)
BREAK
FETCH NEXT FROM Client_Cursor
INTO #Client_ID;
END;
CLOSE Client_Cursor;
DEALLOCATE Client_Cursor;
IF (#AgentCounter >= #MaxAgentCount)
BREAK
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
END;
CLOSE Agent_Cursor;
DEALLOCATE Agent_Cursor;
ERR_HANDLER: PRINT 'ERROR'
END
It breaks on #Client_ID
You can nest fetch_status since the last statement of each loop is fetch next.
The stored proc is failing at below location,Thanks, for all your help.
--Insert MSOrg Information
DECLARE #PersonnelNumber int,
#MSOrg varchar(255)
DECLARE csr CURSOR FAST_FORWARD FOR
SELECT PersonnelNumber FROM Person
OPEN csr
FETCH NEXT FROM csr
INTO #PersonnelNumber
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC GetMSOrg #PersonnelNumber, #MSOrg out
INSERT INTO PersonSubject (
PersonnelNumber
,SubjectID
,SubjectValue
,Created
,Updated
)
SELECT #PersonnelNumber
,SubjectID
,#MSOrg
,getDate()
,getDate()
FROM Subject
WHERE DisplayName = 'MS Org'
FETCH NEXT FROM csr
INTO #PersonnelNumber
END
CLOSE csr
DEALLOCATE csr
Below is the stored prc defination GetMSOrg and fails at third condition
CREATE PROCEDURE [dbo].[GetMSOrg]
(
#PersonnelNumber int
,#OrgTerm varchar(200) out
)
AS
DECLARE #MDRTermID int
,#ReportsToPersonnelNbr int
--Check to see if we have reached the top of the chart
SELECT #ReportsToPersonnelNbr = ReportsToPersonnelNbr
FROM ReportsTo
WHERE PersonnelNumber = #PersonnelNumber
IF (#ReportsToPersonnelNbr IS NULL) --Reached the Top of the Org Ladder
BEGIN
SET #OrgTerm = 'Non-standard rollup'
END
ELSE IF (#PersonnelNumber IN (SELECT PersonnelNumber FROM OrgTermMap))
BEGIN
SELECT #OrgTerm = s.Term
FROM OrgTermMap tm
JOIN Taxonomy..StaticHierarchy s ON tm.OrgTermID = s.TermID
WHERE tm.PersonnelNumber = #PersonnelNumber
END
ELSE
BEGIN
SELECT #MDRTermID = tm.OrgTermID
FROM ReportsTo r
JOIN OrgTermMap tm ON r.ReportsToPersonnelNbr = tm.PersonnelNumber
WHERE r.PersonnelNumber = #PersonnelNumber
IF (#MDRTermID IS NULL)
BEGIN
EXEC GetMSOrg #ReportsToPersonnelNbr, #OrgTerm out
END
ELSE
BEGIN
SELECT #OrgTerm = Term
FROM Taxonomy..StaticHierarchy
WHERE VocabID = 118
AND TermID = #MDRTermID
END
END
GO
Each call to EXEC GetMSOrg keeps progressing along the query
SELECT #ReportsToPersonnelNbr = ReportsToPersonnelNbr
FROM ReportsTo
WHERE PersonnelNumber = #PersonnelNumber
And there is an exit clause when PersonnelNumber no longer reports to anyone.
Therefore the only logical conclusion is that you have a cyclical person->reportsto->..->person. This could even be on a single record.
This query will find loops within the reportsto records:
declare #PersonnelNumber int
set #PersonnelNumber = 10
;with CTE as (
select 1 Level,
convert(varchar(max),#PersonnelNumber) Seed,
'>>' + convert(varchar(max),#PersonnelNumber) + '>>' Path
union all
SELECT Level+1,
convert(varchar(max),ReportsToPersonnelNbr),
Path + convert(varchar(max),ReportsToPersonnelNbr) + '>>'
FROM ReportsTo
join CTE on CTE.Seed = ReportsTo.PersonnelNumber
where Level < 40
)
select *
from CTE
where Len(Replace(Path, '>' + convert(varchar(max),Seed) + '>', ''))
= LEN(Path) - Len('>' + convert(varchar(max),Seed) + '>') * 2