需要sql sp的帮助。我将使用两个表名
从vbscript调用此sptable1
id f-name l_name phone
1 john smith 111-111-1111
2 john doe 222-222-2222
3 peter Wu 333-333-3333
4 peter Wang 444-444-4444
table2
id f-name l_name phone
1 john smith 123-456-1111
2 john doe 234-222-2222
3 peter Wu 345-454-3333
4 peter Wang 456-444-4444
存储过程,首先应该从两个表中得到前1 *并且应该比较table1和table2的第一行并返回所有列名,如果数据不相同,这里存储过程应该返回列“phone” 。 我在sql中很天真,需要帮助来编写这个存储过程。
答案 0 :(得分:0)
通过“前1名”,我认为你的意思是id
:
select ( (case when t1.fname <> t2.fname then 'fname;' else '' end) +
(case when t1.lname <> t2.lname then 'lname;' else '' end) +
(case when t1.phone <> t2.phone then 'phone;' else '' end)
) as diff_columns
from (select top (1) t1.*
from table1 t1
order by id
) cross join
(select top (1) t2.*
from table2 t2
order by id
) ;
我在这个存储过程中看不到多少实用程序。我的猜测是你有一个更复杂的问题(比较两个表)。如果是这样,您应该询问另一个问题。
答案 1 :(得分:0)
CREATE OR ALTER PROCEDURE [dbo].[magicscript__compare_tables]
@left_table nvarchar(200),
@right_table nvarchar(200),
@sql nvarchar(MAX) = null OUT,
@key_fields XML = null,
@not_comparable_columns XML = null,
@execute_generated_query bit = 1,
@print_query bit = 0,
@results_to_table nvarchar(200) = null
AS
BEGIN
SET NOCOUNT ON;
declare @TRUE bit = 1
declare @FALSE bit = 0
declare @object_name int = 1
declare @schema_name int = 2
declare @database_name int = 3
declare @server_name int = 4
declare @left_server_name nvarchar(200) = IIF(PARSENAME(@left_table, @server_name) is null, N'', N'[' + PARSENAME(@left_table, @server_name) + N']' )
declare @left_database_name nvarchar(200) = IIF(PARSENAME(@left_table, @database_name) is null, N'', N'[' + PARSENAME(@left_table, @database_name) + N']')
declare @left_schema_name nvarchar(200) = IIF(PARSENAME(@left_table, @schema_name) is null, N'', N'[' + PARSENAME(@left_table, @schema_name) + N']')
declare @left_object_name nvarchar(200) = N'[' + PARSENAME(@left_table, @object_name) + N']'
declare @left_database_full_name nvarchar(200) = @left_server_name + N'.' + @left_database_name
declare @left_table_full_name nvarchar(200) = @left_database_full_name + N'.' + @left_schema_name + N'.' + @left_object_name + N''
declare @right_server_name nvarchar(200) = IIF(PARSENAME(@right_table, @server_name) is null, N'', N'[' + PARSENAME(@right_table, @server_name) + N']')
declare @right_database_name nvarchar(200) = IIF(PARSENAME(@right_table, @database_name) is null, N'', N'[' + PARSENAME(@right_table, @database_name) + N']')
declare @right_schema_name nvarchar(200) = IIF(PARSENAME(@right_table, @schema_name) is null, N'', N'[' + PARSENAME(@right_table, @schema_name) + N']')
declare @right_object_name nvarchar(200) = N'[' + PARSENAME(@right_table, @object_name) + N']'
declare @right_database_full_name nvarchar(200) = @right_server_name + N'.' + @right_database_name
declare @right_table_full_name nvarchar(200) = @right_database_full_name + N'.' + @right_schema_name + N'.' + @right_object_name + N''
declare @key_column_name nvarchar(200)
declare @column_name nvarchar(200)
declare @sql_column_heder varchar(MAX) = N''
declare @index int = 0
declare @left_column_prefix nvarchar(10) = N'left_'
declare @right_column_prefix nvarchar(10) = N'rigth_'
declare @left_table_alias nvarchar(10) = N'lt'
declare @right_table_alias nvarchar(10) = N'rt'
declare @sql_dif_column varchar(Max) = N''
declare @sql_join_statments nvarchar(4000) = N' ON '
declare @join_keys TABLE (Name nvarchar(200))
declare @ignore_columns TABLE (Name nvarchar(200))
IF (@not_comparable_columns is not null)
BEGIN
INSERT INTO @ignore_columns
SELECT N'[' + Node.Name.value('text()[1]', 'NVARCHAR(200)') + N']' AS Name
FROM @not_comparable_columns.nodes('Columns/Name') AS Node(Name)
END
IF (@key_fields is null)
BEGIN
declare @pks_to_compare TABLE
(
LeftName nvarchar(128),
LeftSystemTypeId tinyint,
LeftMaxLength smallint,
RightName nvarchar(128),
RightSystemTypeId tinyint,
RightMaxLength smallint
)
declare @sql_pk nvarchar(MAX) = N'
SELECT
lt.name,
lt.system_type_id,
lt.max_length,
rt.name,
rt.system_type_id,
rt.max_length
FROM
(
SELECT clm.name, clm.system_type_id, clm.max_length
FROM ' + @left_database_full_name + '.sys.indexes i
INNER JOIN ' + @left_database_full_name + '.sys.index_columns ic
ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
INNER JOIN ' + @left_database_full_name + '.sys.columns clm
ON ic.OBJECT_ID = clm.OBJECT_ID and clm.column_id = ic.column_id
WHERE i.is_primary_key = 1
and ic.OBJECT_ID = OBJECT_ID(''' + @left_table_full_name + ''')
) lt
FULL JOIN
(
SELECT clm.name, clm.system_type_id, clm.max_length
FROM ' + @right_database_full_name + '.sys.indexes i
INNER JOIN ' + @right_database_full_name + '.sys.index_columns ic
ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
INNER JOIN ' + @right_database_full_name + '.sys.columns clm
ON ic.OBJECT_ID = clm.OBJECT_ID and clm.column_id = ic.column_id
WHERE i.is_primary_key = 1
and ic.OBJECT_ID = OBJECT_ID(''' + @right_table_full_name + ''')
) rt
ON lt.name = rt.name'
INSERT INTO @pks_to_compare EXEC(@sql_pk)
IF (NOT EXISTS
(
SELECT 1 FROM @pks_to_compare
WHERE LeftName is null OR RightName is null
OR LeftSystemTypeId != RightSystemTypeId
OR LeftMaxLength != RightMaxLength
) AND EXISTS(SELECT 1 FROM @pks_to_compare))
BEGIN
INSERT INTO @join_keys SELECT N'[' + LeftName + ']' FROM @pks_to_compare
declare @pk_str nvarchar(1024) = N''
select @pk_str += Name + N', ' from @join_keys
print 'Join by primery key(s): ' + @pk_str
END
ELSE
BEGIN
declare @errorMessage nvarchar(500) = N'Primary keys are incompatible or absent in specified tables. You can specify @key_fields parameter to indicate how to join tables. ' + char(13)
+'@key_fields = ''<Columns><Name>col1</Name><Name>col2</Name></Columns>'''
RAISERROR ( @errorMessage, 18, -1);
END
END
ELSE
BEGIN
print 'Join by specified columns'
INSERT INTO @join_keys
SELECT N'[' + Node.Name.value('text()[1]', 'NVARCHAR(200)') + N']' AS Name
FROM @key_fields.nodes('Columns/Name') AS Node(Name)
END
INSERT INTO @ignore_columns SELECT Name FROM @join_keys
declare @ignore_column_str nvarchar(1024) = N''
SELECT @ignore_column_str += Name + N', ' FROM @ignore_columns
print N'Total ignored column(s): ' + @ignore_column_str
print char(13)
DECLARE key_column_cursor CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
SELECT Name FROM @join_keys
OPEN key_column_cursor
FETCH NEXT FROM key_column_cursor INTO @key_column_name
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@index != 0)
BEGIN
SET @sql_join_statments += N' and '
END
SET @sql_join_statments += @left_table_alias + '.' + @key_column_name + ' = ' + @right_table_alias + '.' + @key_column_name + N''
SET @index += 1
FETCH NEXT FROM key_column_cursor INTO @key_column_name
END
CLOSE key_column_cursor;
DEALLOCATE key_column_cursor;
declare @sql_column_cursor nvarchar(1000) = N'
DECLARE column_cursor CURSOR READ_ONLY FAST_FORWARD FOR
SELECT Name FROM
(
SELECT name--, column_Id
FROM ' + @left_database_full_name + '.sys.columns
WHERE Object_ID = Object_ID(''' + @left_table_full_name + ''')
UNION
SELECT name--, column_Id
FROM ' + @right_database_full_name + '.sys.columns
WHERE Object_ID = Object_ID(''' + @right_table_full_name + ''')
) t1 --ORDER BY column_Id'
EXEC(@sql_column_cursor)
SET @index = 0
OPEN column_cursor
FETCH NEXT FROM column_cursor INTO @column_name
WHILE @@FETCH_STATUS = 0
BEGIN
declare @left_column_alias nvarchar(700) = @left_column_prefix + @column_name
declare @right_column_alias nvarchar(700) = @right_column_prefix + @column_name
declare @sql_exist_param_def nvarchar(500) = N'@left_table nvarchar(200), @right_table nvarchar(200), @clmn_name nvarchar(124), @exists bit out'
declare @leftColumnExists bit = 0
declare @sql_left_exists nvarchar(500) = N'SELECT @exists = 1 FROM '
+ @left_database_full_name + '.sys.columns WHERE Name = @clmn_name AND Object_ID = Object_ID(@left_table)'
EXEC sp_executesql @sql_left_exists, @sql_exist_param_def, @left_table_full_name, @right_table_full_name, @column_name, @exists = @leftColumnExists OUT
declare @rightColumnExists bit = 0
declare @sql_right_exists nvarchar(500) = N'SELECT @exists = 1 FROM '
+ @right_database_full_name + '.sys.columns WHERE Name = @clmn_name AND Object_ID = Object_ID(@right_table)'
EXEC sp_executesql @sql_right_exists, @sql_exist_param_def, @left_table_full_name, @right_table_full_name, @column_name, @exists = @rightColumnExists OUT
IF (@leftColumnExists = @TRUE or @rightColumnExists = @TRUE)
BEGIN
declare @left_result_column_name nvarchar(500) = @left_table_alias + N'.[' + @column_name + N']'
declare @right_result_column_name nvarchar(500) = @right_table_alias + N'.[' + @column_name + N']'
IF NOT EXISTS(SELECT 1 FROM @ignore_columns
WHERE Name = N'[' + @column_name + N']')
BEGIN
IF (@leftColumnExists = @TRUE and @rightColumnExists = @TRUE)
BEGIN
SET @sql_dif_column += N' + IIF((' + @left_result_column_name + N' is null and ' + @right_result_column_name + N' is null) or (' + @left_result_column_name + N' = ' + @right_result_column_name + N'), '''', ''' + REPLACE(@column_name, N'att_', N'') + ' | '')' + char(13)
END
ELSE IF ((@leftColumnExists = @TRUE and @rightColumnExists = @FALSE))
BEGIN
SET @sql_dif_column += N' + IIF(' + @left_result_column_name + N' is null, '''', ''' + REPLACE(@column_name, N'att_', N'') + ' | '')' + char(13)
END
ELSE
BEGIN
SET @sql_dif_column += N' + IIF(' + @right_result_column_name + N' is null, '''', ''' + REPLACE(@column_name, N'att_', N'') + ' | '')' + char(13)
END
END
IF (@leftColumnExists = @TRUE)
BEGIN
SET @sql_column_heder += @left_result_column_name + N' ' + @left_column_alias + N',' + char(13)
END
ELSE
BEGIN
SET @sql_column_heder += N'null ' + @left_column_alias + N',' + char(13)
END
IF (@rightColumnExists = @TRUE)
BEGIN
SET @sql_column_heder += @right_result_column_name + N' ' + @right_column_alias + N',' + char(13)
END
ELSE
BEGIN
SET @sql_column_heder += N'null ' + @right_column_alias + N',' + char(13)
END
END
FETCH NEXT FROM column_cursor INTO @column_name
END
CLOSE column_cursor;
DEALLOCATE column_cursor;
SET @sql = N'SELECT * ' + IIF(@results_to_table is null, N'', N'INTO ' + @results_to_table) + char(13)
+ ' FROM ( SELECT ('''' ' + CHAR(13) + @sql_dif_column + N') AS DifferentColumns,' + CHAR(13)
+ @sql_column_heder + ''''' space ' + char(13)
+ N'FROM ' + @left_table_full_name + N' ' + @left_table_alias + char(13)
+ N'FULL JOIN ' + @right_table_full_name + N' ' + @right_table_alias + char(13)
+ @sql_join_statments + char(13)
+ N') t WHERE t.DifferentColumns != N'''' ' + CHAR(13)
IF (@execute_generated_query = @TRUE)
BEGIN
EXEC(@sql)
END
IF(@print_query = @TRUE)
BEGIN
-- https://stackoverflow.com/questions/7850477/how-to-print-varcharmax-using-print-statement/14611173#14611173
END
END
使用方法:
declare @excluded_columns_xml xml = '
<Columns>
<Name>CreatedTime</Name>
<Name>DeletedTime</Name>
</Columns>'
exec [dbo].[magicscript__compare_tables]
@left_table = N'db_name..tb_name_1',
@right_table = N'db_name..tb_name_2',
@not_comparable_columns = @excluded_columns_xml
-- if next arg isn't set or null, procedure doesn't store results to table
--@results_to_table = 'tb_name'
-- by default it uses primiry keys
--@key_fields =
-- N'<Columns>
-- <Name>Name</Name>
-- </Columns>'
另一种情况:
exec [dbo].[magicscript__compare_tables]
@left_table = N'db_name..tb_name_1',
@right_table = N'db_name..tb_name_2',
@key_fields =
N'<Columns>
<Name>Name</Name>
</Columns>'