How can I ignore the ' character into a SQL Server where clause? - sql

I have the following problem with a query on SQL Server
I have this simple query:
SELECT *
FROM [PROT_UTENTI]
WHERE
Nome = 'Paolo D''Aannuntis'
that finds a user by a Nome field (representing the name and the surname, I know, it is horrible but I can't change the DB because it is an old legacy application in production).
As you can see the surname (D'Annuntis) contains the ' character (I escaped it by doubling the '').
The problem is that I am performing this query using the Nome value extracting it from another databse (it is involved into a migration process) where the same Nome field is saved without the ' character into the surname.
So I am performing this query:
SELECT *
FROM [PROT_UTENTI]
WHERE
Nome = 'Paolo DAannuntis'
instead
SELECT *
FROM [PROT_UTENTI]
WHERE
Nome = 'Paolo D''Aannuntis'
finding 0 result.
My question is: there is a way to ignore the ' so the where clause Nome = 'Paolo DAannuntis' can find the same result Nome = 'Paolo D''Aannuntis'?

you can replace any ' by nothing in your search query
SELECT *
FROM [PROT_UTENTI]
WHERE replace(Nome, '''', '') = 'Paolo DAannuntis'
you can also do the replace on both sides
WHERE replace(Nome, '''', '') = replace('Paolo D''Aannuntis', '''', '')
You wrote that the value is extraced from another database in a migration,
so I guess you will have a variable.
declare #nome varchar(100) = 'Paolo D''Aannuntis' -- filled by your process
SELECT *
FROM [PROT_UTENTI]
WHERE replace(Nome, '''', '') = replace(#nome, '''', '')
this will find your row, regardless if there are quotes or not in the variable or in [PROT_UTENTU].nome
this will have affect on the performance of the query, so I hope there are not millions of rows in your table

Related

SQL - Search for WHERE clause with no spaces

I am trying to find a performance smart resolution to searching on data that is coming into an application with character spaces removed, but could exist in the DB system in many ways with spaces. I was thinking the following, but it seems to fail:
select top 1 * where REPLACE(Mfr, ' ', '') = #Mfr and REPLACE(Model, ' ', '') = #Model
Am I doing this completely wrong and is there a better way? It appears to time out only only a DB with 150k records at the moment.
You can implement the expressions as indexed virtual columns for fast lookup.
First you'll need to create the virtual columns:
alter table t add clean_mfr as replace(Mfr, ' ', '');
alter table t add clean_model as replace(Model, ' ', '');
Then you'll index them:
create index ix1 on t (clean_mfr, clean_model);
Now, you can try your query again. Since you are using equality (=) in both virtual columns lookups the query should be instantaneous.
Try:
select top 1 *
from t
where REPLACE(Mfr, ' ', '') = #Mfr and REPLACE(Model, ' ', '') = #Model
Or:
select top 1 *
from t
where clean_mfr = #Mfr and clean_model = #Model

Trouble Getting Columns Names to Variable in SSIS Execute SQL Task

I'm attempting to validate some column headings before the import of a monthly data set. I've set up an Execute SQL Task that's supposed to retrieve the column headings of the prior month's table and store it in Header_Row as a single string with the field names separated by commas. The query runs just fine in SQL Server, but when running in SSIS, it throws the following error:
"The type of the value (Empty) being assigned to variable 'User:Header_Row' differs from the current variable type (String)."
1) Does this mean that I'm not getting anything back from my query?
2) Is there another method I should be using in SSIS to get the query results I'm looking for?
3) Is there an issue with me using the variable reference in my query as a portion of a string? I think the answer is yes, but would like to confirm, as my variable was still empty after changing this.
Original Query:
SELECT DISTINCT
STUFF((
SELECT
',' + COLUMN_NAME
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS aa
WHERE
TABLE_NAME = 'dt_table_?'
ORDER BY
aa.ORDINAL_POSITION
FOR
XML PATH('')
), 1, 1, '') AS Fields
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS a;
EDIT: After changing the variable to cover the full table name, I have a new error saying "The value type (__ComObject) can only be converted to variables of the type Object."
Final Query:
SELECT DISTINCT
CAST(STUFF((
SELECT
',' + COLUMN_NAME
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS aa
WHERE
TABLE_NAME = ?
ORDER BY
aa.ORDINAL_POSITION
FOR
XML PATH('')
), 1, 1, '') As varchar(8000)) AS Fields
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS a;
You are attempting to parameterize your query. Proper query parameterization is useful for avoiding SQL Injection attacks and the like.
Your query is looking for a TABLE_NAME that is literally 'dt_table_?' That's probably not what you want.
For laziness, I'd just rewrite it as
DECLARE #tname sysname = 'dt_table_' + ?;
SELECT DISTINCT
STUFF((
SELECT
',' + COLUMN_NAME
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS aa
WHERE
TABLE_NAME = #tname
ORDER BY
aa.ORDINAL_POSITION
FOR
XML PATH('')
), 1, 1, '') AS Fields
FROM
db_Analytics.INFORMATION_SCHEMA.COLUMNS a;
If that's not working, you might need to use an Expression to build out the query.
I'm really pretty sure that this is your problem:
TABLE_NAME = 'dt_table_?'
I'm guessing this is an attempt to parameterize the query, but having the question mark inside the single-quote will cause the question mark to be taken literally.
Try like this instead:
TABLE_NAME = ?
And when you populate the variable that you use as the parameter value, include the 'dt_table_' part in the value of the variable.
EDIT:
Also in your ResultSet assignment, try changing "Fields" to "0" in the Result Name column.
There are two issues with the query above:
1) The query in the task was not properly parameterized. I fixed this by putting the full name of the prior month's table into the variable.
2) The default length of the result was MAX, which was causing an issue when SSIS would try to put it into my variable, Header_Row. I fixed this by casting the result of the query as varchar(8000).
Thanks for the help everyone.

struggling with creating Insert query

I create Insert statement for organization table like this:
select'Insert into Organizations(Name,ContactPerson,ContactNumber,Mobilenumber)values('''+Nameofthecompany+''+','+Nameofthepersonresponsibleforrecruitment+','+PhoneNumber+','+MobileNumber+''')' from Organization
When I execute this statement I get insert statement. But the issue is where the value is null, it shows all columns null.
Example: (in database)
Name: xxxx
ContactPerson: zzzz
ContactNumber:444444
MobileNumber: null
so my insert statement looks like:
Null.
I want only that column provide null. other details showing properly. Is there any way in sql server? Help me anyone...
The result of concatenating anything to NULL, even itself, is always NULL. Workaround with ISNULL function:
select'Insert into Organizations(Name,ContactPerson,ContactNumber,Mobilenumber)
values('''+ISNULL(Nameofthecompany, 'NULL')+''+','
+ISNULL(Nameofthepersonresponsibleforrecruitment, 'NULL')+','
+ISNULL(PhoneNumber, 'NULL')+','
+ISNULL(MobileNumber, 'NULL')+''')'
from Organization
Demo on SQLFiddle
Sure - just use ISNULL(..) to turn a NULL into e.g. an empty string:
SELECT
'INSERT INTO Organizations(Name, ContactPerson, ContactNumber, Mobilenumber) VALUES(''' +
ISNULL(Nameofthecompany, '') + '' + ',' +
ISNULL(Nameofthepersonresponsibleforrecruitment, '') + ',' +
ISNULL(PhoneNumber, '') + ',' + ISNULL(MobileNumber,'') + ''')'
FROM Organization
When you are adding each of the parameters to the SQL statement, you need to check whether they're null, and if so use the keyword NULL, otherwise include a literal string surrounded with single quotes, but bearing in mind that if the string contains any single quotes, they need to be replaced with two single quotes.
Update the SQL for each parameter something like the following:
CASE WHEN MobileNumber IS NULL THEN 'NULL' ELSE '''' + REPLACE(MobileNumber, '''', '''''') + '''' END

Is there a better way to apply isnull to all columns than what I'm doing?

A number of times over the last month I've had to replace 'null' fields with '0' to every column returned from a query.
to save a lot of time (some of these are returning a high number of columns) I've been using the following and then pasting the results for relevant columns into a new query:
select ', isnull(' + COLUMN_NAME + ', 0)' + ' as ' + COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'summary_by_scca_sales_category '
and TABLE_SCHEMA = 'property''
Essentially I'm wondering if there's a better way that I can do this? Ideally a method where I could automatically apply isnull to all columns being returned in a query (without using two queries).
For example:
I want to take a query like:
select *
from tablename
And for every column returned by * replace null results with 0 without having to write an isnull() line for each column.
edit:
Will accomplish this with a view (doh, should have thought of that). For interests / educations sake is there a way to do something like this with code also?
You could create a VIEW against the tables in question where the ISNULL logic you want is set up. Then queries against the views would return the data you want.
EDIT:
As requested, some sample code to accomplish creating the VIEWs automatically. This is pretty gross, but for something that only has to be run once it will work. Beware of type issues (you stated everything should transmute to 0 so I assume all your columns are of a suitable numeric type):
DECLARE #table_def varchar(max)
SET #table_def = 'CREATE VIEW <tname>_NoNull AS SELECT '
SELECT #table_def = REPLACE(#table_def, '<tname>', t.name) +
'ISNULL(' + c.name + ', 0) AS ' + c.name + ', '
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
WHERE t.name = <<table name>>
SELECT #table_def

How to join attributes in sql select statement?

I want to join few attributes in select statement as one for example
select id, (name + ' ' + surname + ' ' + age) as info from users
this doesn't work, how to do it?
I'm using postgreSQL.
Postgres uses || to concatenate strings; your query needs to be:
select id, (name || ' ' || surname || ' ' || age) as info from users
It should be the key just above the Enter key on a full keyboard, but on mine it's not a sold line - there's a break in the middle of it. You have to hold the Shift key to get the character (called a pipe, btw).
I believe the ANSI standard concatenation operator is: ||
SELECT id, name ||' ' || surname || ' ' || age AS info FROM users
It perfectly might be dependent of the database I would take a look for a concatenation function for the database you are running the select for.
Example. Mysql: CONCAT(name, surname, age).
You may need to cast the fields to a common type before concatenating. In T-SQL for example this would read.
Select id, Cast(name as varchar(50)) + ' ' + Cast(surname as varchar(50)) + ' ' +
Cast(age as varchar(3)) As info From Users
|| is used for this purpose.
Use it like
select name ||' ' ||surname ||' ' ||age as info from users
If you're using mysql or oracle then try CONCAT function:
SELECT id, CONCAT(name, ' ', surname, ' ', age) as info FROM users
That should work as is, but in general it is better not to do too much concatenation sql side if you can help it; rather return all the columns and concat them on the other end.
What are the data types you are using? You may need to CAST / CONVERT into (n)varchar
Make sure your data types are similar and convert any datatypes to string as necessary:
select id, (name + ' ' + surname + ' ' + convert(varchar(3),age)) as info from users
Works fine in most databases I know, although you probably have to CAST the age field to be TEXT. The exact method for doing this depends on the database you're using, which you did not specify.