How to compare data from multiple databases - sql

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;

Related

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

Error in my stored procedure in SQL Server

I try to write stored procedure which will check:
If table and columns exists then we write data
If table not exist then we create it and write data
If table exist then we check existing columns and we write data into exists
columns
This is the code:
CREATE PROCEDURE [dbo].[my_proc] #file_path VARCHAR(1000) = NULL
,#file_type VARCHAR(1000) = NULL
,#file_name VARCHAR(1000) = NULL
,#table_name VARCHAR(1000)
AS
BEGIN
DECLARE #sql NVARCHAR(4000);
SET #table_name = '[dbo].[' + #table_name + ']'
SET #sql = '
DECLARE #msg VARCHAR(max)
--if column and table exist
IF (
EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
) --табличка
AND EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND (
NAME = '' path_file ''
AND NAME = '' file_type ''
AND NAME = '' file_name ''
)
)
) --поля
BEGIN
INSERT INTO ' + #table_name + ' (
file_path
,file_type
,file_name
)
VALUES (
''' + isnull(#file_path, '') + '''
,''' + isnull(#file_type, '') + '''
,''' + isnull(#f ile_name, '') + '''
)
END
--if table not exist
IF NOT EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
)
BEGIN
CREATE TABLE ' + #table_name + ' (
id INT NOT NULL identity(1, 1) PRIMARY KEY
,file_path TEXT
,file_name TEXT
,file_type TEXT
)
END
--if table exist
IF EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
)
BEGIN
--check for columns in table
--file_path
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND (
NAME = ''path_file''
OR NAME = ''file_path''
)
)
BEGIN
PRINT (''NOT COLUMN path_file'')
END
--file name
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', '' U '')
AND NAME = '' file_name ''
)
BEGIN
PRINT ('' NOT COLUMN file_name '')
END
--file_type
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND (
NAME = ''file_type''
OR NAME = ''file_type''
)
)
BEGIN
PRINT (''NOT COLUMN file_type'')
END
ELSE
INSERT INTO ' + #table_name + ' (
file_path
,file_name
,file_type
)
VALUES (
''' + isnull(#file_path, '') + '''
,''' + isnull(#file_name, '') + '''
,''' + isnull(#f ile_type, '') + '''
)
END';
EXEC (#sql);
END
Trouble with already existing table, but without columns I need
Help me please
I tried to run your script and the only error was happening was a miss declared variable.
You were writing "#f ile_name" with an empty space.
BTW I would suggest you to split your code to read. I tried to mess as little as possible.
CREATE PROCEDURE [dbo].[my_proc]
#file_path VARCHAR(1000) = NULL
,#file_type VARCHAR(1000) = NULL
,#file_name VARCHAR(1000) = NULL
,#table_name VARCHAR(1000)
AS
BEGIN
DECLARE #sql NVARCHAR(4000);
DECLARE #msg VARCHAR(max);
SET #table_name = '[dbo].[' + #table_name + ']'
SET #sql = '
--If table not exist then we create it
IF NOT EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N''' + #table_name + ''')
AND type IN (N''U'')
)
BEGIN
CREATE TABLE ' + #table_name + ' (
id INT NOT NULL identity(1, 1) PRIMARY KEY
,file_path TEXT
,file_name TEXT
,file_type TEXT
)
END';
EXEC (#sql);
SET #sql = '
--If table exist then we check existing columns and we write data into exists columns
IF EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
)
BEGIN
PRINT (''TABLE found'')
--check for columns in table
--file_path
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', '' U '')
AND (
NAME = '' path_file ''
OR NAME = ''file_path''
)
)
BEGIN
PRINT (''NOT COLUMN path_file'')
END
--file name
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND NAME = ''file_name''
)
BEGIN
PRINT (''NOT COLUMN file_name'')
END
--file_type
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND (
NAME = ''file_type''
OR NAME = ''file_type''
)
)
BEGIN
PRINT (''NOT COLUMN file_type'')
END
ELSE
INSERT INTO ' + #table_name + ' (
file_path
,file_name
,file_type
)
VALUES (
''' + isnull(#file_path, '') + '''
,''' + isnull(#file_name, '') + '''
,''' + isnull(#file_type, '') + '''
)
END';
EXEC (#sql);
SET #sql = '
--If table and columns exists then we write data
IF (
EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
) --табличка
AND EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(''' + #table_name + ''', ''U'')
AND (
NAME = ''path_file''
AND NAME = ''file_type''
AND NAME = ''file_name''
)
)
) --поля
BEGIN
INSERT INTO ' + #table_name + ' (
file_path
,file_type
,file_name
)
VALUES (
''' + isnull(#file_path, '') + '''
,''' + isnull(#file_type, '') + '''
,''' + isnull(#file_name, '') + '''
)
END';
EXEC (#sql);
END

Generate insert statement which has same columns of a table in SQL Server

I have wide table with 100 columns.
I need a SP which takes 100 parameters and then does the insert.
I know how to do this manually. But having the table definition and knowing that SP parameters will have exact same name of the table columns, can you think of a better/faster way to generate this stored procedure?
I use SQL to write it for you. Check it out and let me know if it needs any tweaks or if you have any questions.
IF OBJECT_ID('yourTable') IS NOT NULL
DROP TABLE yourTable;
CREATE TABLE yourTable
(
col1 INT,
col2 VARCHAR(100),
col3 NUMERIC(18,2)
)
DECLARE #InputParams VARCHAR(MAX),
#InsertColumns VARCHAR(MAX),
#InsertParams VARCHAR(MAX);
WITH CTE_columns
AS
(
SELECT COLUMN_NAME,
UPPER(DATA_TYPE) data_type,
'(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ')' max_length,
CASE
WHEN DATA_TYPE IN ('Numeric','Decimal') THEN CONCAT('(',NUMERIC_PRECISION,',',NUMERIC_SCALE,')')
END prec_scale
--#InsertColumns = COALESCE(#InsertColumns + ',','') + COLUMN_NAME,
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE TABLE_NAME = 'yourTable'
)
SELECT #InputParams = COALESCE(#InputParams + ',','') + CONCAT('#',column_name,' ',data_type,max_length,prec_scale),
#InsertColumns = COALESCE(#InsertColumns + ',','') + COLUMN_NAME,
#InsertParams = COALESCE(#InsertParams + ',','') + '#'+ COLUMN_NAME
FROM CTE_columns
SELECT
'CREATE PROCEDURE dbo.yourProc ' + #InputParams +
' AS
INSERT INTO yourTable(' + #InsertColumns + ')
VALUES (' + #InsertParams + ');
GO'
Results(Formatting isn't great, but it works):
CREATE PROCEDURE dbo.yourProc #col1 INT,#col2 VARCHAR(100),#col3 NUMERIC(18,2) AS
INSERT INTO yourTable(col1,col2,col3)
VALUES (#col1,#col2,#col3);
GO
For this type of scenario, I like to leverage table types.
First, create the table type:
CREATE TYPE [YourType] AS TABLE (columns...)
In C#, populate a DataTable "template" by running this query (using a DataAdapter):
DECLARE #tt AS [YourType]
SELECT * FROM #tt
Then add a row to the table and cycle through the columns to add the necessary values.
Then pass the datatable as a parameter into your procedure:
CREATE PROCEDURE [YourProc]
#tt [YourType] READONLY
AS
BEGIN
--do stuff
END
An added benefit of this approach is that you can pass multiple records into the procedure with a single call.
You can probably quickly modify this for your needs:
Declare #tableName nvarchar(100) = 'aspnet_Membership'
Declare #objectName nvarchar(100) = 'Membership'
DECLARE #newLineChar AS CHAR(2) = CHAR(13) + CHAR(10)
Declare #columnName nvarchar(50)
Declare #dataType nvarchar(50)
Declare #characterLength int
Declare #isNullableString varchar(3)
Declare #ordinalPosition int
Declare #firstSortOrder smallint
Declare #variableTableCreateCode nvarchar(max) = ''
Declare #variableTableDataTypeCode nvarchar(128)
Declare #variableTableSelectCode001 nvarchar(max) = ''
Declare #variableTableSelectCode002 nvarchar(max) = ''
Declare #varableTableInsertIntoCode nvarchar(max) = ''
Declare tbl_ColumnCursor Cursor For
Select colSchema.COLUMN_NAME, colSchema.DATA_TYPE, colSchema.CHARACTER_MAXIMUM_LENGTH, colSchema.IS_NULLABLE , colSchema.ORDINAL_POSITION , FirstSortOrder = CASE WHEN PrimaryKeyDerived.CONSTRAINT_TYPE IS NOT NULL THEN 1 ELSE 2 END
from INFORMATION_SCHEMA.COLUMNS colSchema
LEFT JOIN
(
SELECT
INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
,INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME
,INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
LEFT OUTER JOIN information_schema.KEY_COLUMN_USAGE
ON
INFORMATION_SCHEMA.COLUMNS.TABLE_NAME=information_schema.KEY_COLUMN_USAGE.TABLE_NAME
AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME=information_schema.KEY_COLUMN_USAGE.COLUMN_NAME
LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS
ON
information_schema.KEY_COLUMN_USAGE.TABLE_NAME=information_schema.TABLE_CONSTRAINTS.TABLE_NAME
AND information_schema.KEY_COLUMN_USAGE.CONSTRAINT_NAME=information_schema.TABLE_CONSTRAINTS.CONSTRAINT_NAME
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
) as PrimaryKeyDerived on colSchema.TABLE_NAME = PrimaryKeyDerived.TABLE_NAME and colSchema.COLUMN_NAME = PrimaryKeyDerived.COLUMN_NAME
where colSchema.TABLE_NAME = #tableName
Order By FirstSortOrder , colSchema.ORDINAL_POSITION
Set #variableTableCreateCode = 'declare #' + #objectName + 'Holder table ( ' + #objectName + 'SurrogateKey int , '
Set #variableTableSelectCode001 = 'INSERT INTO #' + #objectName + 'Holder ( '
Set #variableTableSelectCode002 = ' SELECT '
Set #varableTableInsertIntoCode = 'INSERT INTO '+#tableName+' ( '
Open tbl_ColumnCursor
Fetch Next From tbl_ColumnCursor Into #ColumnName, #dataType, #characterLength, #isNullableString, #ordinalPosition , #firstSortOrder
While ##FETCH_STATUS = 0
Begin
print '/#ColumnName/'
print #ColumnName
print ''
print '/##dataType/'
print #dataType
print ''
print '/###isNullableString/'
print #isNullableString
print ''
Select #variableTableDataTypeCode =
case
when #dataType like '%char%' and #characterLength = -1 Then
#dataType+'(max)'
when #dataType like '%char%' and #characterLength = 1 Then
#dataType+'('+convert(varchar(32), #characterLength)+')'
When (#dataType like '%char%') Or (#dataType = 'xml') Or (#dataType like '%text%') Then
#dataType+'('+convert(varchar(32), #characterLength)+')'
Else #dataType
End
Set #variableTableCreateCode = #variableTableCreateCode + ' [' + #columnName + '] ' + #variableTableDataTypeCode +','
select #variableTableSelectCode002 = #variableTableSelectCode002 + 'T.MyEntity.value(''#' + #columnName + ''', '''+#variableTableDataTypeCode+''') AS ' + #columnName + ','
Fetch Next From tbl_ColumnCursor Into #ColumnName, #dataType, #characterLength , #isNullableString , #ordinalPosition , #firstSortOrder
End
Close tbl_ColumnCursor
Deallocate tbl_ColumnCursor
if(DATALENGTH(#variableTableCreateCode) > 0)
BEGIN
select #variableTableCreateCode = LEFT(#variableTableCreateCode, LEN(#variableTableCreateCode) -1)
END
if(DATALENGTH(#variableTableSelectCode002) > 0)
BEGIN
select #variableTableSelectCode002 = LEFT(#variableTableSelectCode002, LEN(#variableTableSelectCode002) -1)
END
Set #variableTableCreateCode = #variableTableCreateCode + #newLineChar + ' ) '
select #variableTableCreateCode
select #variableTableSelectCode001 = #variableTableSelectCode001 + ( SELECT
MyColumns = STUFF
(
(
SELECT ', [' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
/* Optional WHERE Clause */
WHERE
tabs.TABLE_NAME = #tableName
)
select #variableTableSelectCode001 = #variableTableSelectCode001 + ' ) '+#newLineChar
select #variableTableSelectCode002 = #variableTableSelectCode002 + ' FROM #xmldata.nodes(''RootElement/' + #tableName + 'Elements/' + #tableName + 'Element'') AS T(MyEntity); '
select #variableTableSelectCode001 + #variableTableSelectCode002
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ( SELECT
MyColumns = STUFF
(
(
SELECT ', [' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
WHERE
tabs.TABLE_NAME = #tableName
)
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ' ) SELECT '
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ( SELECT
MyColumns = STUFF
(
(
SELECT ', holder.[' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
WHERE
tabs.TABLE_NAME = #tableName
)
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ' from #' + #objectName + 'Holder holder where not exists ( select null from ' +#tableName+ ' realTable where realTable.Name = holder.Name and realTable.IsDeleted = holder.IsDeleted ) '
select #varableTableInsertIntoCode
SELECT
tabs.TABLE_NAME,
MyColumns = STUFF
(
(
SELECT ', alias.[' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
/* Optional WHERE Clause */
WHERE
tabs.TABLE_NAME = #tableName
ORDER BY tabs.TABLE_NAME;

cast list of strings as int list in sql query / stored procedure

I have this stored procedure:
exec SearchResume #KeywordSearch=N'', #GreaterThanDate='2013-09-22 00:00:00',
#CityIDs=N'0,56,31,271,117,327,3,328,228',
#ProvinceIDs=N'0,1,12,13',
#CountryIDs=N'1',
#IndustryIDs=N'0,2,3,4,38,113,114,115,116,117'
Which doesn't return any results because the ids are in nvarchar but the actual values are integer.
Now, when I test the actual SP with a manual list of int values I'm able to get the results, this is the example:
SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN 'Confidential' ELSE LastName + ',' + FirstName END as 'Name',
a.Description 'ResumeTitle',
CurrentTitle,
ModifiedDate,
CASE ISNULL(b.SalaryRangeID, '0') WHEN '0' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END 'Salary',
h.Description 'Relocate',
i.Description + '-' + j.Description + '-' + k.Description 'Location'
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE (b.CityID IN (0,56,31,125,229,5,219,8,228))
AND (b.StateProvinceID IN (0,1,13))
AND (b.CountryID IN (1))
AND (b.IndustryPreferenceID IN (0,2,3,4,5,6,115,116,117))
I would like to know what can I do to send a list of int values, not a list of nvarchar values since as you can see the query doesn't work properly.
Update
Original SP:
ALTER PROCEDURE [dbo].[SearchResume]
#KeywordSearch nvarchar(500),
#GreaterThanDate datetime,
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
AS
BEGIN
DECLARE #sql as nvarchar(4000)
SET #sql = 'SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CurrentEmployerName,
PersonalDescription,
CareerObjectives,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
e.Description ''EducationLevel'',
f.Description ''CareerLevel'',
g.Description ''JobType'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE ( (ModifiedDate > ''' + CAST(#GreaterThanDate as nvarchar(55)) + ''')
'
IF (LEN(#CityIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.CityID IN (' + #CityIDs + '))'
END
IF (LEN(#ProvinceIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.StateProvinceID IN (' + #ProvinceIDs + '))'
END
IF (LEN(#CountryIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.CountryID IN (' + #CountryIDs + '))'
END
IF (LEN(#IndustryIDs) >0)
BEGIN
SET #sql = #sql + 'AND (b.IndustryPreferenceID IN (' + #IndustryIDs + '))'
END
IF (LEN(#KeywordSearch) > 0)
BEGIN
SET #sql = #sql + ' AND (' + #KeywordSearch + ')'
END
SET #sql = #sql + ') ORDER BY ModifiedDate desc'
--select #sql
exec sp_executesql #sql
END
You can create a Table-Valued Function which takes the nVarChar and creates a new record for each value, where you tell it the delimiter. My example here returns a table with a single Value column, you can then use this as a sub query for your IN Selection :
Create FUNCTION [dbo].[fnSplitVariable]
(
#List nvarchar(2000),
#delimiter nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Variable varchar(15),
Value nvarchar(100)
)
AS
BEGIN
Declare #Count int
set #Count = 1
While (Charindex(#delimiter,#List)>0)
Begin
Insert Into #RtnValue (Value, Variable)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#delimiter,#List)-1))),
Variable = 'V' + convert(varchar,#Count)
Set #List = Substring(#List,Charindex(#delimiter,#List)+len(#delimiter),len(#List))
Set #Count = #Count + 1
End
Insert Into #RtnValue (Value, Variable)
Select Value = ltrim(rtrim(#List)), Variable = 'V' + convert(varchar,#Count)
Return
END
Then in your where statement you could do the following:
WHERE (b.CityID IN (Select Value from fnSplitVariable(#CityIDs, ','))
I have included your original Procedure, and updated it to use the function above:
ALTER PROCEDURE [dbo].[SearchResume]
#KeywordSearch nvarchar(500),
#GreaterThanDate datetime,
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
AS
BEGIN
DECLARE #sql as nvarchar(4000)
SET #sql = N'
DECLARE #KeywordSearch nvarchar(500),
#CityIDs nvarchar(500),
#ProvinceIDs nvarchar(500),
#CountryIDs nvarchar(500),
#IndustryIDs nvarchar(500)
SET #KeywordSearch = '''+#KeywordSearch+'''
SET #CityIDs = '''+#CityIDs+'''
SET #ProvinceIDs = '''+#ProvinceIDs+'''
SET #CountryIDs = '''+#CountryIDs+'''
SET #IndustryIDs = '''+#IndustryIDs+'''
SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CurrentEmployerName,
PersonalDescription,
CareerObjectives,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
e.Description ''EducationLevel'',
f.Description ''CareerLevel'',
g.Description ''JobType'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE ( (ModifiedDate > ''' + CAST(#GreaterThanDate as nvarchar(55)) + ''')
'
IF (LEN(#CityIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.CityID IN (Select Value from fnSplitVariable(#CityIDs,'','') ))'
END
IF (LEN(#ProvinceIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.StateProvinceID IN (Select Value from fnSplitVariable(#ProvinceIDs,'','') ))'
END
IF (LEN(#CountryIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.CountryID IN (Select Value from fnSplitVariable(#CountryIDs,'','') ))'
END
IF (LEN(#IndustryIDs) >0)
BEGIN
SET #sql = #sql + N'AND (b.IndustryPreferenceID IN (Select Value from fnSplitVariable(#IndustryIDs,'','') ))'
END
IF (LEN(#KeywordSearch) > 0)
BEGIN
SET #sql = #sql + N' AND (' + #KeywordSearch + ')'
END
SET #sql = #sql + N') ORDER BY ModifiedDate desc'
--select #sql
exec sp_executesql #sql
END
DECLARE #SQL AS NVARCHAR(MAX)
SET #SQL = 'SELECT DISTINCT
UserID,
ResumeID,
CASE a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
a.Description ''ResumeTitle'',
CurrentTitle,
ModifiedDate,
CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
h.Description ''Relocate'',
i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
JOIN JobType g ON b.JobTypeID = g.JobTypeID
JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
JOIN City i ON b.CityID = i.CityID
JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
JOIN Country k ON k.CountryID = b.CountryID
WHERE (b.CityID IN (' + #CityIDs + '))
AND (b.StateProvinceID IN (' + #ProvinceIDs + '))
AND (b.CountryID IN (' + #CountryIDs + '))
AND (b.IndustryPreferenceID IN (' + #IndustryIDs + '))'
EXEC #SQL
You could do a split on the id's that are coming in to the store procedure. So consider this split function:
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
Then you could write your where statement like this:
WHERE
EXISTS(SELECT NULL FROM dbo.Split(#CityIDs,',') AS city
WHERE city.Data=b.CityID)
AND EXISTS(SELECT NULL FROM dbo.Split(#ProvinceIDs,',') AS Province
WHERE Province.Data=b.StateProvinceID)
AND EXISTS(SELECT NULL FROM dbo.Split(#CountryIDs,',') AS Country
WHERE Country.Data=b.CountryID)
AND EXISTS(SELECT NULL FROM dbo.Split(#IndustryIDs,',') AS Industry
WHERE Industry.Data=b.IndustryPreferenceID)

PostgreSQL Create new table out of rows

I am using PostgreSQL 9.1
I have the following table containing some settings
setting | content
---------------+---------
enabled | True
reenable_time | 1
count_row | 6
count_col | 3
(4 rows)
And I want to have something like this
enabled | reenable_time | count_row | count_col
---------+-----------------+-------------+----------
True | 1 | 6 | 3
(1 row)
Thank you for your answers!
What you need is cross-tabulation (pivoting), aka turning rows into columns.
If you don't want to hardcode "enabled", "reenable_time", etc., you need to use dynamic SQL.
The basic idea goes like this:
SELECT -- Grab the user_account columns.
acc.id,
acc.email,
-- Use max() combined with a case statement to
-- usher individual attribute values into columns.
max(CASE WHEN (attr.attribute_type = 'first-name')
THEN attr.value END) AS fname,
max(CASE WHEN (attr.attribute_type = 'last-name')
THEN attr.value END) AS lname,
max(CASE WHEN (attr.attribute_type = 'title')
THEN attr.value END) AS title
FROM user_account AS acc
-- Join the attribute table /once/.
LEFT JOIN user_attribute AS attr
ON (attr.user_account_id = acc.id)
WHERE (acc.email = 'foo#example.com')
-- Group by the non-pivoted columns
GROUP BY acc.id,acc.email;
Here a link for further information:
https://sykosomatic.org/2011/09/pivot-tables-in-postgresql/
Here an example from my workplace (it's MS-SQL, but you'll get the idea, PostGre doesn't support the pivot command, it's MS proprietary, so you need to use "case when" with "group by"):
-- ===================================================
-- Author: Stefan Steiger
-- Create date: 14.04.2011
-- Last modified: 17.01.2012
-- Description: Übersetzung für Berichte
-- ===================================================
CREATE PROCEDURE [dbo].[sp_RPT_Report_Translation]
#in_mandant varchar(3)
,#in_sprache varchar(2)
,#in_stichtag varchar(50)
,#in_report_name nvarchar(1000)
AS
BEGIN
DECLARE
#strSQL NVARCHAR(MAX)
,#strReportName NVARCHAR(1000)
,#strPivotColumns NVARCHAR(MAX)
,#stichtag DATETIME
-- Abrunden des Eingabedatums auf 00:00:00 Uhr
SET #stichtag = CONVERT(DATETIME, #in_stichtag)
SET #stichtag = CAST(FLOOR(CAST(#stichtag AS Float)) AS DateTime)
SET #in_stichtag = CONVERT(varchar(50), #stichtag)
SET NOCOUNT ON;
SET #strReportName = REPLACE(#in_report_name, N'''', '''''')
-- http://geekswithblogs.net/baskibv/archive/2008/07/03/123567.aspx
SELECT
#strPivotColumns = COALESCE(#strPivotColumns, '') + '[' + [RTR_ItemCaption] + '], '
FROM T_RPT_Translations
WHERE (RTR_Status = 1)
AND (RTR_MDT_ID = #in_mandant)
AND
(
(RTR_ReportName = #strReportName)
OR
(RTR_ReportName = 'PARA_ALL')
)
--AND (RTR_ItemCaption != 'RPT_Title')
AND (RTR_ItemCaption IS NOT NULL)
AND
(
(RTR_IsFlag != 1)
OR
(RTR_IsFlag IS NULL)
)
AND (RTR_ItemCaption != '')
ORDER BY RTR_Sort
SET #strPivotColumns = SUBSTRING(#strPivotColumns, 0, LEN(#strPivotColumns))
SET #strPivotColumns = REPLACE(#strPivotColumns, N'''', '''''')
--PRINT #strPivotColumns
SET #strSQL = '
SELECT TOP(1) * FROM
(
SELECT
RTR_ItemCaption
--,RTR_Kurz_' + #in_sprache + '
,RTR_Lang_' + #in_sprache + '
FROM T_RPT_Translations
WHERE (RTR_MDT_ID = ''' + #in_mandant+ ''')
AND
(
(RTR_ReportName = ''' + #strReportName + ''')
OR
(RTR_ReportName = ''PARA_ALL'')
)
--AND (RTR_ItemCaption != ''RPT_Title'')
AND (RTR_Status = 1)
AND (RTR_ItemCaption IS NOT NULL)
AND
(
(RTR_IsFlag != 1)
OR
(RTR_IsFlag IS NULL)
)
AND (RTR_ItemCaption != '''')
) AS SourceTable
PIVOT
(
MAX(RTR_Lang_' + #in_sprache + ')
FOR RTR_ItemCaption IN
( '
+ #strPivotColumns +
' )
) AS PivotTable
--ORDER BY RPT_RM_SO_Bezeichnung, RPT_RM_GB_Bezeichnung, RPT_RM_NutzungGruppeCode
'
DECLARE #ProzedurParameter nvarchar(max)
SET #ProzedurParameter = '
DECLARE #in_mandant varchar(3)
,#in_sprache varchar(2)
,#in_stichtag varchar(50)
,#in_report_name nvarchar(1000)
;
SET #in_mandant = ''' + REPLACE(#in_mandant, '''', '''''') + ''';
SET #in_sprache = ''' + REPLACE(#in_sprache, '''', '''''') + ''';
SET #in_stichtag = ''' + REPLACE(#in_stichtag, '''', '''''') + ''';
SET #in_report_name = ''' + REPLACE(#in_report_name, '''', '''''') + ''';
'
EXECUTE sp_RPT_DEBUG_LOG_ProzedurRun
'sp_RPT_Report_Translation'
,#ProzedurParameter
,#strSQL
,'' --#ProzedurDetail
;
--PRINT #strSQL
EXECUTE (#strSQL)
END
GO