Function Within a View SQL Server Management Studio - sql

Hey I am having a problem with a View I am trying to create I am trying to get the Full Address of a member be Displayed in correlation with the MemberID of my Member Table along with a few other fields in other tables but the FullAddress and MFullAddress are both coming up as NULL Values and I am not sure why hope someone can help. Below is the Code for my View.
SELECT dbo.Member.MemberID, dbo.Member.Title + ' ' + dbo.Member.Forename + ' ' + dbo.Member.Surname AS Fullname, dbo.GetMemberFullAddress(dbo.Member.MemberID) AS FullAddress,
dbo.GetMemberFullMailingAddress(dbo.Member.MemberID) AS MFullAddress, dbo.Lookup_ActionType.Description, dbo.Payment.Amount
FROM dbo.Payment RIGHT OUTER JOIN
dbo.Member ON dbo.Payment.PaymentID = dbo.Member.MemberID RIGHT OUTER JOIN
dbo.Action LEFT OUTER JOIN
dbo.Lookup_ActionType ON dbo.Action.ActionTypeID = dbo.Lookup_ActionType.ActionTypeID ON dbo.Member.MemberID = dbo.Action.MemberID
WHERE (dbo.Member.MemberID = dbo.Member.MemberID)
And here are Both of my Functions Called dbo.GetFullMemberAddress The Mfulladdress function is the same only different fields
USE [ICOM.Database]
GO
/****** Object: UserDefinedFunction [dbo].[GetMemberFullAddress] Script Date: 22/10/2014 11:53:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Richard Glass>
-- Create date: <22/10/2014>
-- Description: <Returns Full Address>
-- =============================================
ALTER FUNCTION [dbo].[GetMemberFullAddress]
-- Add the parameters for the function here
(#MemberID as integer)
RETURNS varchar(250)
AS
BEGIN
DECLARE #AddressLine as varchar(40)
DECLARE #FullAddress as varchar(250)
SET #FullAddress = (SELECT LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) AS FullName FROM Member WHERE MemberID = #MemberID) + CHAR(10)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
SET #AddressLine = (SELECT Member.AddressLine1 FROM Member WHERE MemberID = #MemberID)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
SET #AddressLine = (SELECT AddressLine2 FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT AddressLine3 FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT Town FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT PostCode FROM Member WHERE MemberID = #MemberID)
SET #FullAddress = #FullAddress + #AddressLine
RETURN #FullAddress
END
AND

The problem is because concatenetating NULL with anything yields NULL by default. At the start of the function you have:
DECLARE #AddressLine as varchar(40)
DECLARE #FullAddress as varchar(250)
SET #FullAddress = (SELECT LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) AS FullName FROM Member WHERE MemberID = #MemberID) + CHAR(10)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
And the problem line is:
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
At this point #AddressLine is NULL, therefore you set #FullAddress to NULL.
You can get your full address though in a much less convoluted fashion, something like:
(LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) + ',' +
CASE WHEN ISNULL(AddressLine1, '') = '' THEN '' ELSE AddressLine1 + ',' END +
CASE WHEN ISNULL(AddressLine2, '') = '' THEN '' ELSE AddressLine2 + ',' END +
CASE WHEN ISNULL(AddressLine3, '') = '' THEN '' ELSE AddressLine3 + ',' END +
CASE WHEN ISNULL(Town, '') = '' THEN '' ELSE Town + ',' END +
CASE WHEN ISNULL(PostCode, '') = '' THEN '' ELSE PostCode END
Although seemingly quite verbose, it does not require repeatedly querying the member table. You could then just add this as a computed column:
I would be inclined to add MemberAddress as a computed column to dbo.Member though, something like:
ALTER TABLE dbo.Member
ADD MemberAddress AS
(LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) + ',' +
CASE WHEN ISNULL(AddressLine1, '') = '' THEN '' ELSE AddressLine1 + ',' END +
CASE WHEN ISNULL(AddressLine2, '') = '' THEN '' ELSE AddressLine2 + ',' END +
CASE WHEN ISNULL(AddressLine3, '') = '' THEN '' ELSE AddressLine3 + ',' END +
CASE WHEN ISNULL(Town, '') = '' THEN '' ELSE Town + ',' END +
CASE WHEN ISNULL(PostCode, '') = '' THEN '' ELSE PostCode END;

Would your stored proc be better if the code was just this?
DECLARE #FullAddress as varchar(250)
SELECT FullAddress = LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname)
+ CHAR(10)
+ ISNULL(Member.AddressLine1 + CHAR(10),'')
+ ISNULL(Member.AddressLine2 + CHAR(10),'')
+ ISNULL(Member.AddressLine3 + CHAR(10),'')
+ ISNULL(Member.Town + CHAR(10),'')
+ ISNULL(Member.PostCode + CHAR(10),'')
FROM Member
WHERE MemberID = #MemberID
RETURN #FullAddress

Related

Syntax error in SQL , Incorrect syntax near ''

What is wrong in this?
The error comes from this section;
AND ('''+#searchText+''' = '''' OR (ISNULL(CAST(t1.id as varchar(10)),'''') + '' '' +
ISNULL(CAST(FORMAT(t1.reading_date,#dateformat) as varchar(12)),'''')+'' '' +
ISNULL(t2.description,'''') + '' '' +
ISNULL(t3.equipment_no,'''') + '' '' +
ISNULL(t4.description,'''') + '' '' +
ISNULL(CAST(t1.actual_usage as nvarchar(16)),'''') + '' '' +
ISNULL(t5.uom_code,'''') + '' '' +
ISNULL(CAST(t1.actual_cost as nvarchar(16)),'''') + '' '' +
ISNULL(t6.currency_code,'''') + '' '' +
ISNULL(t1.comment,'''') + '' '' +
ISNULL(CAST(FORMAT(t1.actual_date,#dateformat) as varchar(12)),'''')) LIKE ''%'' '''+#searchText+''' ''%'')
The error:
Msg 102, Level 15, State 1, Line 59
Incorrect syntax near ''.
You can use CONCAT(string1, string2, ...., string_n) instead of doing it manually using + operator. Also, use COALESCE to return column value or empty string. This will simplify the query.
Sample for using CONCAT()
DECLARE #searchText AS VARCHAR(50) = 'SearchMe'
DECLARE #sqlQuery2 AS VARCHAR(5000)
DECLARE #Column1 AS VARCHAR(50) = 'TestValue1'
SET #sqlQuery2 = ' FROM Table
WHERE Column1 = ''' + #Column1 + '''
AND ('''+#searchText+''' = '''' OR (CONCAT(
ISNULL(CAST(t1.id as varchar(10)), '''')
, '' ''
, ISNULL(CAST(FORMAT(t1.reading_date,#dateformat) as varchar(12)), '''')
, '' ''
, ISNULL(t2.description, '''')
, '' ''
, ISNULL(t3.equipment_no, '''')
, '' ''
, ISNULL(t4.description, '''')
, '' ''
, ISNULL(CAST(t1.actual_usage as nvarchar(16)), '''')
, '' ''
, ISNULL(t5.uom_code, '''')
, '' ''
, ISNULL(CAST(t1.actual_cost as nvarchar(16)), '''')
, '' ''
, ISNULL(t6.currency_code, '''')
, '' ''
, ISNULL(t1.comment, '''')
, '' ''
, ISNULL(CAST(FORMAT(t1.actual_date,#dateformat) as varchar(12)), ''''))
)) LIKE ''% ' + #searchText + ' %''
)
ORDER BY someColumn '
select #sqlQuery2
Also noted that LIKE statement string in your code will return syntax error.
Replace the string
LIKE ''%'' ''' + #searchText + ''' ''%''
by this
LIKE ''% ' + #searchText + ' %''
I hope it will help.

sp_help_revlogin causing loss of characters on LOGINs with Unicode characters

I want to export all users of SQL Server and I found following stored procedure from the documentation but when I Ran the Procedure, the results of some names just exported as ??????. For example:
-- Login: ??????
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'??????')
BEGIN
CREATE LOGIN [??????] WITH PASSWORD = 0x0200B27F654A0090DFA7C3C857709164CDC91F1 HASHED, SID = 0x27926CE54FA0E64BB2300AE2E104C22C, DEFAULT_DATABASE = [master], DEFAULT_LANGUAGE = [us_english], CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF
EXEC master.dbo.sp_addsrvrolemember #loginame='?????', #rolename='sysadmin'
END
All of Unicode users was shown as ?????? . the SP is as follow:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[sp_help_revlogin]
(
#login_name sysname = NULL
)
AS
BEGIN
DECLARE #name SYSNAME
DECLARE #type VARCHAR (1)
DECLARE #hasaccess INT
DECLARE #denylogin INT
DECLARE #is_disabled INT
DECLARE #PWD_varbinary VARBINARY (256)
DECLARE #PWD_string VARCHAR (514)
DECLARE #SID_varbinary VARBINARY (85)
DECLARE #SID_string VARCHAR (514)
DECLARE #tmpstr VARCHAR (1024)
DECLARE #is_policy_checked VARCHAR (3)
DECLARE #is_expiration_checked VARCHAR (3)
Declare #Prefix VARCHAR(255)
DECLARE #defaultdb SYSNAME
DECLARE #defaultlanguage SYSNAME
DECLARE #tmpstrRole VARCHAR (1024)
IF (#login_name IS NULL)
BEGIN
DECLARE login_curs CURSOR
FOR
SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin, p.default_language_name
FROM sys.server_principals p
LEFT JOIN sys.syslogins l ON ( l.name = p.name )
WHERE p.type IN ( 'S', 'G', 'U' )
AND p.name <> 'sa'
ORDER BY p.name
END
ELSE
DECLARE login_curs CURSOR
FOR
SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin, p.default_language_name
FROM sys.server_principals p
LEFT JOIN sys.syslogins l ON ( l.name = p.name )
WHERE p.type IN ( 'S', 'G', 'U' )
AND p.name = #login_name
ORDER BY p.name
OPEN login_curs
FETCH NEXT FROM login_curs INTO #SID_varbinary, #name, #type, #is_disabled, #defaultdb, #hasaccess, #denylogin, #defaultlanguage
IF (##fetch_status = -1)
BEGIN
PRINT 'No login(s) found.'
CLOSE login_curs
DEALLOCATE login_curs
RETURN -1
END
SET #tmpstr = '/* sp_help_revlogin script '
PRINT #tmpstr
SET #tmpstr = '** Generated ' + CONVERT (varchar, GETDATE()) + ' on ' + ##SERVERNAME + ' */'
PRINT #tmpstr
PRINT ''
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
PRINT ''
SET #tmpstr = '-- Login: ' + #name
PRINT #tmpstr
SET #tmpstr='IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'''+#name+''')
BEGIN'
Print #tmpstr
IF (#type IN ( 'G', 'U'))
BEGIN -- NT authenticated account/group
SET #tmpstr = 'CREATE LOGIN ' + QUOTENAME( #name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + #defaultdb + ']'
END
ELSE
BEGIN -- SQL Server authentication
-- obtain password and sid
SET #PWD_varbinary = CAST( LOGINPROPERTY( #name, 'PasswordHash' ) AS varbinary (256) )
EXEC sp_hexadecimal #PWD_varbinary, #PWD_string OUT
EXEC sp_hexadecimal #SID_varbinary,#SID_string OUT
-- obtain password policy state
SELECT #is_policy_checked = CASE is_policy_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END
FROM sys.sql_logins
WHERE name = #name
SELECT #is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END
FROM sys.sql_logins
WHERE name = #name
SET #tmpstr = 'CREATE LOGIN ' + QUOTENAME( #name ) + ' WITH PASSWORD = ' + #PWD_string + ' HASHED, SID = '
+ #SID_string + ', DEFAULT_DATABASE = [' + #defaultdb + ']' + ', DEFAULT_LANGUAGE = [' + #defaultlanguage + ']'
IF ( #is_policy_checked IS NOT NULL )
BEGIN
SET #tmpstr = #tmpstr + ', CHECK_POLICY = ' + #is_policy_checked
END
IF ( #is_expiration_checked IS NOT NULL )
BEGIN
SET #tmpstr = #tmpstr + ', CHECK_EXPIRATION = ' + #is_expiration_checked
END
END
IF (#denylogin = 1)
BEGIN -- login is denied access
SET #tmpstr = #tmpstr + '; DENY CONNECT SQL TO ' + QUOTENAME( #name )
END
ELSE IF (#hasaccess = 0)
BEGIN -- login exists but does not have access
SET #tmpstr = #tmpstr + '; REVOKE CONNECT SQL TO ' + QUOTENAME( #name )
END
IF (#is_disabled = 1)
BEGIN -- login is disabled
SET #tmpstr = #tmpstr + '; ALTER LOGIN ' + QUOTENAME( #name ) + ' DISABLE'
END
SET #Prefix = '
EXEC master.dbo.sp_addsrvrolemember #loginame='''
SET #tmpstrRole=''
SELECT #tmpstrRole = #tmpstrRole
+ CASE WHEN sysadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''sysadmin''' ELSE '' END
+ CASE WHEN securityadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''securityadmin''' ELSE '' END
+ CASE WHEN serveradmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''serveradmin''' ELSE '' END
+ CASE WHEN setupadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''setupadmin''' ELSE '' END
+ CASE WHEN processadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''processadmin''' ELSE '' END
+ CASE WHEN diskadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''diskadmin''' ELSE '' END
+ CASE WHEN dbcreator = 1 THEN #Prefix + [LoginName] + ''', #rolename=''dbcreator''' ELSE '' END
+ CASE WHEN bulkadmin = 1 THEN #Prefix + [LoginName] + ''', #rolename=''bulkadmin''' ELSE '' END
FROM (
SELECT CONVERT(VARCHAR(100),SUSER_SNAME(sid)) AS [LoginName],
sysadmin,
securityadmin,
serveradmin,
setupadmin,
processadmin,
diskadmin,
dbcreator,
bulkadmin
FROM sys.syslogins
WHERE ( sysadmin<>0
OR securityadmin<>0
OR serveradmin<>0
OR setupadmin <>0
OR processadmin <>0
OR diskadmin<>0
OR dbcreator<>0
OR bulkadmin<>0
)
AND name=#name
) L
PRINT #tmpstr
PRINT #tmpstrRole
PRINT 'END'
END
FETCH NEXT FROM login_curs INTO #SID_varbinary, #name, #type, #is_disabled, #defaultdb, #hasaccess, #denylogin, #defaultlanguage
END
CLOSE login_curs
DEALLOCATE login_curs
RETURN 0
END
GO
The number of users registered in the system as Unicode is large and it takes a long time to transfer them manually. So I need a solution that I can use to display Unicode users correctly.
I'll preface this by saying that it's much better to do this via some tool, rather than cobbling together something in T-SQL. You can use SSMS or similar.
Be that as it may:
The script you have posted has multiple issues.
The primary issue you were facing: use of varchar instead of nvarchar, means that other languages get clobbered.
Use of a cursor unnecessarily. This can be done in a single query using string aggregation.
The binary-to-hex procedure is complete overkill, as this can be done with a simple CONVERT. Even if it were necessary, it could have been done with an inline TVF.
Some missing QUOTENAME usages, to quote the names correctly.
It only adds fixed server roles, rather than any user-defined roles
It only adds CONNECT permissions, rather than any other permissions.
Usage of the deprecated sys.syslogins, which was replaced in 2005.
The following script is a full rewrite.
It returns all SQL logins and Windows logins based on AD users or AD groups (but not any other logins such as certificate based ones).
It adds all server-level permissions.
It adds all server roles, including user-defined.
CREATE OR ALTER PROCEDURE [dbo].[sp_help_revlogin]
#login_name sysname = NULL
AS
SELECT
'
/* sp_help_revlogin script
** Generated ' + CONVERT(nvarchar(30), GETDATE()) + ' on ' + QUOTENAME(##SERVERNAME) + ' */
GO
' + STRING_AGG(CONCAT(
'
IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = N',
QUOTENAME(p.name, ''''),
')
BEGIN
CREATE LOGIN ',
QUOTENAME(p.name),
CASE WHEN p.type IN ('G', 'U') THEN ' FROM WINDOWS' END,
' WITH',
CASE WHEN p.type = 'S' THEN CONCAT(
' PASSWORD = ',
CONVERT(nvarchar(max), ISNULL(l.password_hash, 0x0), 1),
' HASHED, SID = ',
CONVERT(nvarchar(max), p.sid, 1),
CASE WHEN l.is_policy_checked = 0 THEN ', CHECK_POLICY = OFF' END,
CASE WHEN l.is_expiration_checked = 1 THEN ', CHECK_EXPIRATION = ON' END,
','
) END,
' DEFAULT_DATABASE = ',
QUOTENAME(p.default_database_name),
', DEFAULT_LANGUAGE = ',
QUOTENAME(p.default_language_name),
';
END;
GO
',
CASE WHEN p.is_disabled = 1 THEN
'ALTER LOGIN ' + QUOTENAME(p.name) + ' DISABLE;
GO
'
END,
r.roles + '
GO
',
sp.perms + '
GO
'
), N'
') WITHIN GROUP (ORDER BY p.name)
FROM sys.server_principals p
LEFT JOIN sys.sql_logins l ON l.principal_id = p.principal_id
CROSS APPLY (
SELECT STRING_AGG(
'EXEC sp_addsrvrolemember #loginame = ' + p2.name + ', #rolename = ' + QUOTENAME(r.name, '''') + ';'
, '
GO
'
)
FROM sys.server_role_members rm
JOIN sys.server_principals r ON r.principal_id = rm.role_principal_id
CROSS APPLY (VALUES( QUOTENAME(p.name, '''') )) p2(name) -- error 8124
WHERE rm.member_principal_id = p.principal_id
) r(roles)
CROSS APPLY (
SELECT STRING_AGG(CONCAT(
CASE WHEN sp.state = 'W' THEN N'GRANT' ELSE sp.state_desc END,
' ',
sp.permission_name COLLATE DATABASE_DEFAULT,
' TO ',
p2.name,
CASE WHEN sp.state = 'W' THEN N' WITH GRANT OPTION' END,
';'
), N'
GO
'
)
FROM sys.server_permissions sp
CROSS APPLY (VALUES( QUOTENAME(p.name, '''') )) p2(name) -- error 8124
WHERE sp.grantee_principal_id = p.principal_id
AND sp.class = 100
) sp(perms)
WHERE p.type IN ('S', 'G', 'U')
AND p.name <> 'sa'
AND (p.name = #login_name OR #login_name IS NULL);
GO
db<>fiddle

How to compare data from multiple databases

I'm trying to compare some data from different multiple databases, as I have illustrate my current case, I have there databases, database 1 is the main, and time to time database 2 and database 3 are updated from database 1. I have some difficulties to get the final result which return the data from database 1 and two columns column show the availability in database 2 as Yes or No, and the same with second extra column that will indicate the data availability on the database 3 with Yes or NO.
SELECT *
FROM (
Select ID as db1_ID,
First_name as db1_First_name,
Last_name as db1_Last_name,
Email as db1_Email,
Password as db1_Password,
Request_Id as db1_Request_Id,
User_Id as db1_User_Id,
Request_name as db1_Request_name
from User
inner join User_request
on User_request.User_Id = user.ID
) AS DB1_VIEW
LEFT OUTER JOIN
(
Select ID as db2_ID,
First_name as db2_First_name,
Last_name as db2_Last_name,
Email as db2_Email,
Password as db2_Password,
Request_Id as db2_Request_Id,
User_Id as db2_User_Id,
Request_name as db2_Request_name
from User
inner join User_request
on User_request.User_Id = user.ID
) AS DB2_VIEW
ON db2_ID = db1_ID
LEFT OUTER JOIN
(
Select ID as db3_ID,
First_name as db3_First_name,
Last_name as db3_Last_name,
Email as db3_Email,
Password as db3_Password,
Request_Id as db3_Request_Id,
User_Id as db3_User_Id,
Request_name as db3_Request_name
from User
inner join User_request
on User_request.User_Id = user.ID
) AS DB3_VIEW
ON db3_ID = db1_ID
ID First_name Last_name Email Password Request_Id User_Id Request_name
1 Oliver Jake OJake#domain.com 123 1 1 Request1
2 Mathew Harry MHarry#domain.com 123 1 2 Request1
3 Jacob Reece JReece#domain.com 123 1 3
Request1
4 Charlie Damian CDamian#domain.com 123 1 4 Request1
Use this as your first select statement:
SELECT DB1_VIEW.*
,CASE WHEN DB2_VIEW.db2_ID IS NOT NULL THEN 'Y' ELSE 'N' END AS Available_db2
,CASE WHEN DB3_VIEW.db3_ID IS NOT NULL THEN 'Y' ELSE 'N' END AS Available_db3
You can remove all the details apart from the ID fields in the db2_view and db3_view subqueries.
You can use the below query before execute you should use replace [SourceDB] to your source database and [TargertDB] to your target database. Insert the table name into #mdtables to include for comparison.
USE [SourceDB]
IF Object_id('tempdb..#mdTables') IS NOT NULL
DROP TABLE #mdtables;
CREATE TABLE #mdtables
(
id INT IDENTITY(1, 1) NOT NULL,
schemaname NVARCHAR(128),
tablename NVARCHAR(128)
);
INSERT INTO #mdtables
(schemaname,
tablename)
VALUES ('dbo',
'user');
DECLARE #mdTableLim INT =0,
#mdTableRowId INT =0
SELECT #mdTableLim = Count(*)
FROM #mdtables;
SET #mdTableRowId = 1;
WHILE #mdTableRowId <= #mdTableLim
BEGIN
DECLARE #SDBName VARCHAR(50) = '[SourceDB]',
#TDBName VARCHAR(50) = '[TargertDB]',
#tableName VARCHAR(100) = ''
DECLARE #WhereF VARCHAR(max) ='',
#joincondition VARCHAR(max) ='',
#or VARCHAR(10) ='',
#select VARCHAR(max) = '',
#comma VARCHAR(1)='',
#query VARCHAR(max) ='',
#and VARCHAR(5)='',
#where1 VARCHAR(1000) ='',
#wOR VARCHAR(5)=''
SELECT #tableName = tablename
FROM #mdtables
WHERE id = #mdTableRowId;
SELECT #joincondition += Isnull(#and + ( CASE
WHEN cu.column_name IS NULL
THEN
NULL
ELSE ' src.[' + cu.column_name
+
'] = ' +
'trgt.['
+ c.column_name + ']'
END ), ''),
#WhereF += Isnull (#or + ( CASE
WHEN cu.column_name IS NOT NULL THEN
NULL
ELSE Isnull ( ' src.[' +
TC.column_name
+
'] ',
' isnull( src.[' +
C.column_name +
'],1) ' )
+ Isnull( '<> trgt.[' +
TC.column_name
+ ']',
' = isnull (src.['
+
C.column_name + '],1) ')
END ), ''),
#or = ( CASE
WHEN cu.column_name IS NOT NULL THEN ''
ELSE ' OR '
END ),
#and = ( CASE
WHEN cu.column_name IS NULL THEN ''
ELSE ' AND '
END ),
#select += #comma + ' src.[' + c.column_name + '] '
+ Isnull (' , trgt.[' + TC.column_name + ']', ''),
#comma = ',',
#where1 += Isnull(( #wOR + ( CASE
WHEN cu.column_name IS NULL THEN
NULL
ELSE ' trgt.[' + cu.column_name +
'] is null '
END ) ), ''),
#wOR = ( CASE
WHEN cu.column_name IS NULL THEN ''
ELSE ' OR '
END )
FROM information_schema.columns C
LEFT JOIN information_schema.key_column_usage CU
ON C.column_name = cu.column_name
AND constraint_name LIKE 'PK_%'
AND c.table_name = cu.table_name
LEFT JOIN [TargertDB].information_schema.columns TC
ON C.column_name = TC.column_name
AND c.table_name = TC.table_name
WHERE c.table_name = #tableName
--AND columnproperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 0
AND c.column_name NOT IN ( 'LST_CHG_TMS', 'LST_CHG_TMS',
'LST_CHG_USR_ID'
,
'LST_CHG_USR_ID' )
AND c.data_type NOT IN ( 'image' )
ORDER BY cu.column_name
SET #query = 'select ' + #select + ' from ' + #SDBName + '.dbo.'
+ #tableName + ' as src left join ' + #TDBName
+ '.dbo.' + #tableName + ' as trgt on '
+ #joincondition + ' where (' + #where1 + ')'
+ Isnull ('and '+ NULLIF (#WhereF, ''), '')
DECLARE #qu1 VARCHAR(max) =
' declare #cnt int =0 select #cnt =count (1) from '
+ #SDBName + '.dbo.' + #tableName
+ ' as src left join ' + #TDBName + '.dbo.'
+ #tableName + ' as trgt on ' + #joincondition
+ ' where (' + #where1 + ')'
+ Isnull (' OR '+ NULLIF (#WhereF, ''), '')
+ ' if (#cnt>0) begin select '''
+ #tableName + ''' as [ ],#cnt ' +-- #query + ' end '
BEGIN try
EXECUTE ( #qu1)
END try
BEGIN catch
PRINT #qu1;
END catch
SET #mdTableRowId = #mdTableRowId + 1
END
This might not need CTE's or sub-queries.
A few joins might do it.
SELECT
Usr1.ID AS db1_User_Id,
Usr1.First_name AS db1_First_name,
Usr1.Last_name AS db1_Last_name,
Usr1.Email AS db1_Email,
Usr1.Password AS db1_Password,
MAX(UsrReq1.Request_Id) AS db1_Request_Id,
MAX(UsrReq1.Request_name) AS db1_Request_name,
CASE WHEN COUNT(UsrReq2.User_Id) > 0 THEN 'Y' ELSE 'N' END AS Available_Db2,
CASE WHEN COUNT(UsrReq3.User_Id) > 0 THEN 'Y' ELSE 'N' END AS Available_Db3
FROM [Database1].[User] AS Usr1
LEFT JOIN [Database1].[User_request] AS UsrReq1 ON UsrReq1.User_Id = Usr1.ID
LEFT JOIN [Database2].[User] AS Usr2 ON Usr2.ID = Usr1.ID
LEFT JOIN [Database2].[User_request] AS UsrReq2 ON UsrReq2.User_Id = Usr2.ID
LEFT JOIN [Database3].[User] AS Usr3 ON Usr3.ID = Usr1.ID
LEFT JOIN [Database3].[User_request] AS UsrReq3 ON UsrReq3.User_Id = Usr3.ID
GROUP BY
Usr1.ID,
Usr1.First_name,
Usr1.Last_name,
Usr1.Email,
Usr1.Password;

SQL Server: Error message on dynamic procecure

I don't have much experience with dynamic procedures so the following was only an attempt.
The only part that is actually dynamic here is the table name which I tried to create by combining the fix part "MOC_" and the variable part #level.
Can someone tell me what I have to change here to make this work ?
The error I get when executing this points to the IF NOT EXISTS part:
Conversion failed when converting the nvarchar value 'IF NOT EXISTS (
SELECT *
FROM MOC_Nav2
WHERE itemID = ' to data type int.
My procedure:
ALTER PROCEDURE [dbo].[MOC_UpdateNav]
#level nvarchar(20),
#itemID int,
#parentID int,
#itemName nvarchar(100),
#sortID int,
#logStatus nvarchar(20),
#lastUpdate nvarchar(50),
#modBy varchar(50)
AS
BEGIN
SET NOCOUNT ON;
BEGIN
DECLARE #sql nvarchar(max)
SET #sql = 'IF NOT EXISTS
(
SELECT *
FROM MOC_' + #level + '
WHERE itemID = ' + #itemID + '
)
INSERT INTO MOC_' + #level + '
(
parentID,
itemName,
sortID,
logStatus,
lastUpdate,
modDate,
modBy
)
SELECT ' + #parentID + ',
' + #itemName + ',
' + #sortID + ',
' + #logStatus + ',
' + #lastUpdate + ',
GETDATE(),
' + #modBy + '
ELSE
UPDATE MOC_' + #level + '
SET parentID = ' + #parentID + ',
itemName = ' + #itemName + ',
sortID = ' + #sortID + ',
logStatus = ' + #logStatus + ',
lastUpdate = ' + #lastUpdate + ',
modDate = GETDATE(),
modBy = ' + #modBy + '
WHERE itemID = ' + #itemID + ''
EXEC(#sql)
END
END
#itemID is an int. Because it is used in the expression, everything else must be converted to a number, including your SQL text.
Convert #itemID (and other numbers) to nvarchar before concatenating it into the query:
SET #sql = N'IF NOT EXISTS
(
SELECT *
FROM MOC_' + #level + '
WHERE itemID = ' + cast(#itemID as nvarchar(30)) + ...

SQL trigger only returning one record during a delete

Below is a trigger I've created for a table in a SQL database (We are running SQL Server 2008). We are going to be doing updates, inserts, and deletes in bulk so we created this trigger and a "storage" table (TransactionLog) to capture all the activity. So far, this trigger works perfectly for inserts and updates. All the records wind up in the "storage" table with all appropriate values.
However, the problem occurs when we try to delete anything more than one record. The only record this trigger captures and sends to the "storage" table is the last record deleted. All others get lost.
CREATE TRIGGER [dbo].[trg_Agent_ALL]
ON [dbo].[Agent]
FOR INSERT, UPDATE, DELETE
AS
BEGIN
--TransactionLog variables
DECLARE #tableName char(25) = 'Agent'
DECLARE #transDate datetime
DECLARE #lastChangeOperator char(6)
DECLARE #tableString char(255)
DECLARE #action char(1) = 'I'
DECLARE #userId char(25)
--Trigger table variables
DECLARE #sNumber char(10)
DECLARE #controlId char(3)
DECLARE #entityType char(1)
DECLARE #firstName nvarchar(50)
DECLARE #lastName nvarchar(50)
DECLARE #suffix nvarchar(10)
DECLARE #corpName nvarchar(100)
IF EXISTS (SELECT * FROM deleted)
BEGIN
SET #action =
CASE
WHEN EXISTS (SELECT * FROM inserted) THEN 'U'
ELSE 'D'
END
END
IF #action = 'D'
BEGIN
SELECT #sNumber = sNumber, #lastChangeOperator = LastChangeOperator, #transDate = LastChangeDate, #entityType = EntityType,
#firstName = FirstName, #lastName = LastName, #suffix = NameSuffix, #corpName = CorporateName, #controlId = ControlId
FROM deleted
IF #firstName IS NULL SET #firstName = 'NULL'
IF #lastName IS NULL SET #lastName = 'NULL'
IF #suffix IS NULL SET #suffix = 'NULL'
IF #corpName IS NULL SET #corpName = 'NULL'
IF #controlId IS NULL SET #controlId = 'NULL'
SET #tableString = 'sNum:' + #sNumber + ' ' + 'EntType:' + #entityType + ' ' + 'Fname:' + #firstName + ' ' + 'Lname:' + #lastname + ' ' + 'suf:' + #suffix +
' ' + 'crpName:' + #corpName + ' ' + 'crlId:' + #controlId
END
ELSE
BEGIN
SELECT #sNumber = SymetraNumber, #lastChangeOperator = LastChangeOperator, #transDate = LastChangeDate, #entityType = EntityType,
#firstName = FirstName, #lastName = LastName, #suffix = NameSuffix, #corpName = CorporateName, #controlId = ControlId
FROM inserted
IF #firstName IS NULL SET #firstName = 'NULL'
IF #lastName IS NULL SET #lastName = 'NULL'
IF #suffix IS NULL SET #suffix = 'NULL'
IF #corpName IS NULL SET #corpName = 'NULL'
IF #controlId IS NULL SET #controlId = 'NULL'
SET #tableString = 'sNum:' + #sNumber + ' ' + 'EntType:' + #entityType + ' ' + 'Fname:' + #firstName + ' ' + 'Lname:' + #lastname + ' ' + 'suf:' + #suffix +
' ' + 'crpName:' + #corpName + 'crlId:' + #controlId
END
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
VALUES (#transDate, 'Op', #tableName, #action, #tableString, #lastChangeOperator)
END
Based on the comments below I've altered the SQL code in the delete section. The hard-coded values seem to be working, however the main reason I placed them in there just to show those are the values I need for those specific columns. I have variables set with these values in the code above (see the DECLARE statements). This, however, is giving me the following error message:
Conversion failed when converting the varchar value 'P' to data type int.
This error is coming off of the EntityType attribute in the inner SELECT statement. What confuses me is that this column has a data type set to char(1), and the TableString column (the destination of the concatenated values) has a data type of nvarchar(255). No clue where the "int" is coming from...
IF #action = 'D'
BEGIN
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
SELECT LastChangeDate, 'Op', 'Agent', 'D',
(SELECT CAST(CAST(sNumber as nvarchar) + ' ' + EntityType + ' ' + ISNULL(FirstName, ' ') + ' ' + ISNULL(LastName, ' ') + ' ' + ISNULL(NameSuffix, ' ') + ' ' +
ISNULL(CorporateName, ' ' ) + ' ' + ISNULL(CAST(ControlId as nvarchar), ' ') AS nvarchar) as TableString
FROM deleted), LastChangeOperator
FROM deleted
END
ELSE
EDIT
By casting the sNumber and controlId fields to nvarchar I was able to move past my previous error message. Right now, however I am receiving a different error message posted below:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
FINAL EDIT
Altering the subquery like so allowed me to return multiple deleted records into the Audit table as I was only requesting one record at a time.
IF #action = 'D'
BEGIN
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
SELECT LastChangeDate, 'Op', 'Agent', 'D',
CAST('SymNum:' + CAST(SymetraNumber as nvarchar(30)) + ' entType:' + EntityType + ' Fname:' + ISNULL(FirstName, 'NULL') + ' Lname:' + ISNULL(LastName, 'NULL') +
' suff:' + ISNULL(NameSuffix, 'NULL') + ' corpName:' + ISNULL(CorporateName, 'NULL' ) + ' ctrlId:' + ISNULL(CAST(ControlId as nvarchar(30)), 'NULL') AS nvarchar(30)) as TableString
, LastChangeOperator
FROM deleted
END
ELSE
That select #sNumber = sNumber, .. syntax will overwrite the variables once for each row, so you end up only with the last row's values.
And then you also do an insert into ... values (...), which can only insert one row.
You should try to rewrite it in the form:
insert into TransactionLog ( ... )
select sNumber, ... from deleted
You can use ISNULL(lastname, 'NULL') instead of your if-statements.