Reputation: 109
I have a database with several tables and I need to search every varchar
column across the database, for columns that simultaneously contain lower and upper case characters.
To clarify:
If one column contains helLo
the name of the column should be returned by the query, but if the column values only contain either hello
or HELLO
then the name of the column is not returned.
Upvotes: 6
Views: 15774
Reputation: 25152
You can check the hash compared to its upper and lower values... here is a simple test:
declare @test varchar(256)
set @test = 'MIX' -- Try changing this to a mix case, and then all lower case
select case
when hashbytes('SHA1',@test) <> hashbytes('SHA1',upper(@test)) and hashbytes('SHA1',@test) <> hashbytes('SHA1',lower(@test))
then 'MixedCase'
else 'Not Mixed Case'
end
So using this in a table... you can do something like this
create table #tempT (SomeColumn varchar(256))
insert into #tempT (SomeColumn) values ('some thing lower'),('SOME THING UPPER'),('Some Thing Mixed')
SELECT SomeColumn
FROM #tempT
WHERE 1 = case
when hashbytes('SHA1',SomeColumn) <> hashbytes('SHA1',upper(SomeColumn)) and hashbytes('SHA1',SomeColumn) <> hashbytes('SHA1',lower(SomeColumn)) then 1
else 0
end
Upvotes: 0
Reputation: 13344
Let's exclude all UPPER and all LOWER, the rest will be MIXED.
SELECT someColumn
FROM someTable
WHERE someColumn <> UPPER(someColumn) AND someColumn <> LOWER(someColumn)
EDIT:
As suggested in comments and described in detail here I need to specify a case-sensitive collation.
SELECT someColumn
FROM someTable
WHERE someColumn <> UPPER(someColumn) AND
someColumn <> LOWER(someColumn)
Collate SQL_Latin1_General_CP1_CS_AS
Upvotes: 9
Reputation: 12243
I think I understand that you want to find any varchar column with mixed case data within it?
If so, you can achieve this with a cursor
looking at your column types, which then executes some dynamic SQL on the varchar
columns it finds to check the data for mixed case values.
I thoroughly recommend doing this on a non-production server using a copy of your database, not least because you need to create a table to deposit your findings into:
create table VarcharColumns (TableName nvarchar(max), ColumnName nvarchar(max))
declare @sql nvarchar(max)
declare my_cursor cursor local static read_only forward_only
for
select 'insert into VarcharColumns select t,c from(select ''' + s.name + '.' + tb.name + ''' t, ''' + c.name + ''' c from ' + s.name + '.' + tb.name + ' where ' + c.name + ' like ''%[abcdefghijklmnopqrstuvwxyz]%'' COLLATE SQL_Latin1_General_CP1_CS_AS and ' + c.name + ' like ''%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%'' COLLATE SQL_Latin1_General_CP1_CS_AS having count(1) > 0) a' as s
from sys.columns c
inner join sys.types t
on(c.system_type_id = t.system_type_id
and t.name = 'varchar'
)
inner join sys.tables tb
on(c.object_id = tb.object_id)
inner join sys.schemas s
on(tb.schema_id = s.schema_id)
open my_cursor
fetch next from my_cursor into @sql
while @@fetch_status = 0
begin
print @sql
exec(@sql)
fetch next from my_cursor into @sql
end
close my_cursor
deallocate my_cursor
select * from VarcharColumns
Upvotes: 0
Reputation: 147344
It sounds like you are after a case sensitive search, so you'd need to use a case sensitive collation for there WHERE clause.
e.g. if your collation is currently SQL_Latin1_General_CP1_CI_AS which is case insensitive, you can write a case sensitive query using:
SELECT SomeColumn
FROM dbo.SomeTable
WHERE SomeField LIKE '%helLo%' COLLATE SQL_Latin1_General_CP1_CS_AS
Here, COLLATE SQL_Latin1_General_CP1_CS_AS
tells it to use a case sensitive collation to perform the filtering.
Upvotes: 3