Search button, datatype missmatch - sql

i am trying to do a search button which can search for both surname and user id from just one search bar,
SELECT user_id, Title, FirstName, Surname, Address, PostCode, PhoneNumber
from [User]
WHERE (Not (user_id)=100003)
and (user_id= '$ID' or Surname ='ID')
order by user_id
this issue is, user_id is and int and surname is nvarchard datatype, so is i search for user id i get the output, but when i search for surname i get the error -
Conversion failed when converting the varchar value 'nes' to data type int
any help would be appriciated

The problem here is 'nes' isn't a valid number. SQL Server doesn't know how to look for this value in an integer column.
You can work around this by casting your INT field into a nVarChar. Here's an example:
-- What we are searching for.
DECLARE #SearchFor NVARCHAR(255) = '1';
-- Use a CTE to create some sample records to search.
WITH SampleData AS
(
/* Create some sample records.
*/
SELECT
r.[User_Id],
r.Name
FROM
(
VALUES
(1, 'Tom'),
(2, 'Dick'),
(3, 'Harry')
) AS r([User_Id], Name)
)
SELECT
*
FROM
SampleData
WHERE
#SearchFor IN (CAST([User_id] AS NVARCHAR(255)), Name)
;

Related

SQL Server HASHBYTES function returning un

I'm using the HASHBYTES function in T-SQL to generate an MD5 hash of some data, but I am getting some unexpected results, even though hashing the same data. What am I doing wrong here?
For demonstration purposes I'll create a table and insert a random guid as the 'CustomerId' and a random email address as the 'EmailAddress'. The 'ConcatHash' is a computed column which should create an MD5 hash of the two columns joined together by the pipe character. So it's easier to see whats going on I have also added a ConcatColumn so you can see what the CONCAT_WS is doing.
CREATE TABLE dbo.CustomerTest
(
CustomerId UNIQUEIDENTIFIER NOT NULL
, EmailAddress VARCHAR(255) NOT NULL
, ConcatColumn AS (CONCAT_WS('|', CustomerId, EmailAddress))
, ConcatHash AS (HASHBYTES('MD5', CONCAT_WS('|', CustomerId, EmailAddress))) PERSISTED
)
GO
INSERT INTO dbo.CustomerTest
VALUES
('8E38101D-988E-4BF1-B8F1-E8E0B8DAA891', 'a1jfapedu#adhoc-orange.com')
GO
SELECT * FROM dbo.CustomerTest
Here is the result...
I'll now query the same data from a different table, using CONCAT_WS and HASHBYTES in exactly the same way as I did previously.
SELECT CustomerId
, Email
, CONCAT_WS('|', CustomerId, Email) As ConcatColumn
, HASHBYTES('MD5', CONCAT_WS('|', CustomerId, Email)) AS ConcatHash
FROM dbo.Customers
WHERE CustomerId = '8E38101D-988E-4BF1-B8F1-E8E0B8DAA891'
Here is the result...
Here are the results side-by-side, and you can see the data is the same, the concatanated data is the same, yet the MD5 is different...
To save you the trouble of looking at the 'ConcatColumn' column letter by letter, I have already verified they are identical. So why is the MD5 hash different?
varchar and nvarchar columns do not produce the same hash results...
-- Setup demo data...
create table dbo.Customers1 (
CustomerId varchar(255),
Email varchar(255),
);
insert dbo.Customers1 (CustomerId, Email) values
('8E38101D-988E-4BF1-B8F1-E8E0B8DAA891', 'a1jfapedu#adhoc-orange.com');
create table dbo.Customers2 (
CustomerId varchar(255),
Email nvarchar(255),
);
insert dbo.Customers2 (CustomerId, Email) values
('8E38101D-988E-4BF1-B8F1-E8E0B8DAA891', 'a1jfapedu#adhoc-orange.com');
-- Query data...
SELECT CustomerId
, Email
, HASHBYTES('MD5', CONCAT_WS('|', CustomerId, Email)) AS ConcatHash
FROM dbo.Customers1
WHERE CustomerId = '8E38101D-988E-4BF1-B8F1-E8E0B8DAA891'
SELECT CustomerId
, Email
, HASHBYTES('MD5', CONCAT_WS('|', CustomerId, Email)) AS ConcatHash
FROM dbo.Customers2
WHERE CustomerId = '8E38101D-988E-4BF1-B8F1-E8E0B8DAA891'
Which yields...
CustomerId
Email
ConcatHash
8E38101D-988E-4BF1-B8F1-E8E0B8DAA891
a1jfapedu#adhoc-orange.com
0xB3CF062CD2FAB8601A1B58E53D1F705B
and...
CustomerId
Email
ConcatHash
8E38101D-988E-4BF1-B8F1-E8E0B8DAA891
a1jfapedu#adhoc-orange.com
0xFACC935D24A15B73B4F6B864D3BA536

How can insert value by selecting from another

I have three tables. table1 for insert data and table2, table3 for selecting data.
table1:
int id,
varchar name,
varchar gender,
varchar category,
table2:
int id,
varchar gender,
table3:
int id,
varchar category,
According to these tables, i'm using stored procedure as below:
Create procedure ABC
(
#id varchar(10),
#name varchar(11),
#gender varchar(10),
#category varchar(10)
)
As
begin
Insert into table1(id, name, gender, category) select #id, #name, g.id, c.id from gender g, category c where g.gender=#gender and c.category=#category
end
Now, using this if gender or category is empty then data is not inserting. Please tell me where i'm wrong and tell best query to insert data using select query. Please help me to solve the problem. Thanks
You are using and in where clause which means only if gender = #gender then it is selecting any record.
Create procedure ABC
(
#id int, ----- change this to int since id is int type in your table
#name varchar(11),
#gender varchar(10)='',
#category varchar(10)=''
)
As
begin
Insert into table1(id, name, gender, category)
select #id, #name, g.id, c.id from gender g, category c
where (g.gender=#gender or isnull(#gender,'')='') and (c.category=#category or isnull(#category,'')='')
end
Although you may use this approach. But since you want to insert id of gender and category column in your table, then on passing null or blank value what is your expected id to be put in your record.
It is better if you first check gender and category value in your respected table and if record not found then insert it in your table and then save its corresponding id in your final table.

SQL if else filter in single select statement

Is it possible to output the following:
for each group by personId, if email ends with '#company.com' then filter by [where type = 'h'] else filter [where type = 't']
so the query would output the following:
1 bob#hotmail.com h
2 bill#hotmail.com t
create table #emails (personId int, email nvarchar(100), type char(1) )
insert into #emails values (1, 'bob#company.com', 't');
insert into #emails values (1, 'bob#hotmail.com', 'h');
insert into #emails values (2, 'bill#hotmail.com', 't');
insert into #emails values (2, 'bill#gmail.com', 'h');
select * from #emails
drop table #emails
Thanks
This is based on the description of the logic, not the sample results.
I think you want boolean logic in the where clause:
where (email like '%#company.com' and type = 'h') or
(email not like '%#company.com' and type = 't')
This particular version assumes that email is never NULL. It is easy enough to incorporate that into the logic.
EDIT:
I see, this is a prioritization query:
select top (1) with ties e.*
from #emails e
order by row_number() over (partition by personId
order by (case when email like '%#company.com' and type = 'h' then 1
when type = 't' then 2
else 3
end)
);
You can exclude type column from the insert and use a computed field instead, as below:
create table #emails (personId int, email nvarchar(100), type as case when email like '%#company.com' then 'h' else 't' end)
Like that all your inserts will automatically have the type column handled
EDIT: If you still want to perform an update after words just use the same CASE statement in the select.
It's kinda hard to understand the question, but I think you are looking for something like this:
SELECT personId, email, type
FROM #emails t0
WHERE type = CASE WHEN EXISTS(
SELECT 1
FROM #emails t1
WHERE t0.personId = t1.personId
AND t1.email LIKE '%#company.com'
) THEN 'h' ELSE 't' END
This will give the desired results, so the text of the question should be something like "when there is a record for that person with email ends with #company.com then type h otherwise type t.
If I get it right. Your #company.com is a default value to email column. So, you want to get the actual email, which will be the next email for each person. I'm not sure about the type column why you're trying to using it, as (in my opinion) doesn't matter if is it h or t as long as we can exclude emails that ends with #company.com directly with this simple query :
SELECT *
FROM #emails
WHERE
RIGHT(email, 11) <> 'company.com'
from there you can expand the where clause as much conditions as needed.

How do I search for ALL words within ANY columns of multiple Full Text indexes?

If I have two full text indexes on tables such as Contacts and Companies, how can I write a query that ensures ALL the words of the search phrase exist within either of the two indexes?
For example, if I'm searching for contacts where all the keywords exist in either the contact record or the company, how would I write the query?
I've tried doing CONTAINSTABLE on both the contact and company tables and then joining the tables together, but if I pass the search phrase in to each as '"searchTerm1*' AND '"searchTerm2*"' then it only matches when all the search words are on both indexes and returns too few records. If I pass it in like '"searchTerm1*' OR '"searchTerm2*"' then it matches where any (instead of all) of the search words are in either of the indexes and returns too many records.
I also tried creating an indexed view that joins contacts to companies so I could search across all the columns in one shot, but unfortunately a contact can belong to more than one company and so the ContactKey that I was going to use as the key for the view is no longer unique and so it fails to be created.
It seems like maybe I need to break the phrase apart and query for each word separately and then join the results back together to be able to ensure all the words were matched on, but I can't think of how I'd write that query.
Here's an example of what the model could look like:
Contact CompanyContact Company
-------------- -------------- ------------
ContactKey ContactKey CompanyKey
FirstName CompanyKey CompanyName
LastName
I have a Full Text index on FirstName,LastName and another on CompanyName.
This answer is rebuilt to address your issue such that multiple strings must exist ACROSS the fields. Note the single key in the CompanyContactLink linking table:
CREATE FULLTEXT CATALOG CompanyContact WITH ACCENT_SENSITIVITY = OFF
GO
CREATE TABLE Contact ( ContactKey INT IDENTITY, FirstName VARCHAR(20) NOT NULL, LastName VARCHAR(20) NOT NULL )
ALTER TABLE Contact ADD CONSTRAINT PK_Contact PRIMARY KEY NONCLUSTERED ( ContactKey )
CREATE TABLE Company ( CompanyKey INT IDENTITY, CompanyName VARCHAR(50) NOT NULL )
ALTER TABLE Company ADD CONSTRAINT PK_Company PRIMARY KEY NONCLUSTERED ( CompanyKey )
GO
CREATE TABLE CompanyContactLink ( CompanyContactKey INT IDENTITY NOT NULL, CompanyKey INT NOT NULL, ContactKey INT NOT NULL )
GO
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Dipper', 'Pines' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Mabel', 'Pines' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Stanley', 'Pines' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Soos', 'Ramirez' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Wendy', 'Corduroy' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Sheriff', 'Blubs' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Bill', 'Cipher' )
INSERT INTO Contact ( FirstName, LastName ) VALUES ( 'Pine Dip', 'Nobody' )
INSERT INTO Contact ( FirstNAme, LastName ) VALUES ( 'Nobody', 'Pine Dip' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Mystery Shack' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Greesy Diner' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Watertower' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Manotaur Cave' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Big Dipper Watering Hole' )
INSERT INTO Company ( CompanyName ) VALUES ( 'Lost Pines Dipping Pool' )
GO
INSERT INTO CompanyContactLink Values (3, 5), (1, 1), (1, 2), (1, 3), (1, 4), (1,5), (5,1), (3,1), (4,1)
GO
CREATE FULLTEXT INDEX ON Contact (LastName, FirstName)
KEY INDEX PK_Contact
ON CompanyContact
WITH STOPLIST = SYSTEM
CREATE FULLTEXT INDEX ON Company (CompanyName)
KEY INDEX PK_Company
ON CompanyContact
WITH STOPLIST = SYSTEM
GO
CREATE VIEW CompanyContactView
WITH SCHEMABINDING
AS
SELECT
CompanyContactKey,
CompanyName,
FirstName,
LastName
FROM
dbo.CompanyContactLink
INNER JOIN dbo.Company ON Company.CompanyKey = CompanyContactLink.CompanyKey
INNER JOIN dbo.Contact ON Contact.ContactKey = CompanyContactLink.ContactKey
GO
CREATE UNIQUE CLUSTERED INDEX idx_CompanyContactView ON CompanyContactView (CompanyContactKey);
GO
CREATE FULLTEXT INDEX ON CompanyContactView (CompanyName, LastName, FirstName)
KEY INDEX idx_CompanyContactView
ON CompanyContact
WITH STOPLIST = SYSTEM
GO
-- Wait a few moments for the FULLTEXT INDEXing to take place.
-- Check to see how the index is doing ... repeat the following line until you get a zero back.
DECLARE #ReadyStatus INT
SET #ReadyStatus = 1
WHILE (#ReadyStatus != 0)
BEGIN
SELECT #ReadyStatus = FULLTEXTCATALOGPROPERTY('CompanyContact', 'PopulateStatus')
END
SELECT
CompanyContactView.*
FROM
CompanyContactView
WHERE
FREETEXT((FirstName,LastName,CompanyName), 'Dipper') AND
FREETEXT((FirstName,LastName,CompanyName), 'Shack')
GO
And for the sake of your example with Wendy at the Watertower:
SELECT
CompanyContactView.*
FROM
CompanyContactView
WHERE
FREETEXT((FirstName,LastName,CompanyName), 'Wendy') AND
FREETEXT((FirstName,LastName,CompanyName), 'Watertower')
GO
I created a method that works with any number full text indexes and columns. Using this method, it is very easy to add additional facets to search for.
Split the search phrase into rows in a temp table
Join to this temp table to search for each search term using CONTAINSTABLE on each applicable full text index.
Union the results together and get the distinct count of the search terms found.
Filter out results where the number of search terms specified does not match the number of search terms found.
Example:
DECLARE #SearchPhrase nvarchar(255) = 'John Doe'
DECLARE #Matches Table(
MentionedKey int,
CoreType char(1),
Label nvarchar(1000),
Ranking int
)
-- Split the search phrase into separate words.
DECLARE #SearchTerms TABLE (Term NVARCHAR(100), Position INT)
INSERT INTO #SearchTerms (Term, Position)
SELECT dbo.ScrubSearchTerm(Term)-- Removes invalid characters and convert the words into search tokens for Full Text searching such as '"word*"'.
FROM dbo.SplitSearchTerms(#SearchPhrase)
-- Count the search words.
DECLARE #numSearchTerms int = (SELECT COUNT(*) FROM #SearchTerms)
-- Find the matching contacts.
;WITH MatchingContacts AS
(
SELECT
[ContactKey] = sc.[KEY],
[Ranking] = sc.[RANK],
[Term] = st.Term
FROM #SearchTerms st
CROSS APPLY dbo.SearchContacts(st.Term) sc -- I wrap my CONTAINSTABLE query in a Sql Function for convenience
)
-- Find the matching companies
,MatchingContactCompanies AS
(
SELECT
c.ContactKey,
Ranking = sc.[RANK],
st.Term
FROM #SearchTerms st
CROSS APPLY dbo.SearchCompanies(st.Term) sc
JOIN dbo.CompanyContact cc ON sc.CompanyKey = cc.CompanyKey
JOIN dbo.Contact c ON c.ContactKey = cc.ContactKey
)
-- Find the matches where ALL search words were found.
,ContactsWithAllTerms AS
(
SELECT
c.ContactKey,
Ranking = SUM(x.Ranking)
FROM (
SELECT ContactKey, Ranking, Term FROM MatchingContacts UNION ALL
SELECT ContactKey, Ranking, Term FROM MatchingContactCompanies
) x
GROUP BY c.ContactKey
HAVING COUNT(DISTINCT x.Term) = #numSearchTerms
)
SELECT
*
FROM ContactsWithAllTerms c
Update
Per the comments, here's an example of my SearchContacts function. It's just a simple wrapper function because I was using it in multiple procedures.
CREATE FUNCTION [dbo].[SearchContacts]
(
#contactsKeyword nvarchar(4000)
)
RETURNS #returntable TABLE
(
[KEY] int,
[RANK] int
)
AS
BEGIN
INSERT #returntable
SELECT [KEY],[RANK] FROM CONTAINSTABLE(dbo.Contact, ([FullName],[LastName],[FirstName]), #contactsKeyword)
RETURN
END
GO

Insert values of one table in a database to another table in another database

I would like to take some data from a table from DB1 and insert some of that data to a table in DB2.
How would one proceed to do this?
This is what I've got so far:
CREATE VIEW old_study AS
SELECT *
FROM dblink('dbname=mydb', 'select name,begins,ends from study')
AS t1(name varchar(50), register_start date, register_end date);
/*old_study now contains the data I wanna transfer*/
INSERT INTO studies VALUES (nextval('studiesSequence'),name, '',3, 0, register_start, register_end)
SELECT name, register_start, register_end from old_study;
This is how my table in DB2 looks:
CREATE TABLE studies(
id int8 PRIMARY KEY NOT NULL,
name_string VARCHAR(255) NOT NULL,
description VARCHAR(255),
field int8 REFERENCES options_table(id) NOT NULL,
is_active INTEGER NOT NULL,
register_start DATE NOT NULL,
register_end DATE NOT NULL
);
You should include the column names in both the insert and select:
insert into vip_employees(name, age, occupation)
select name, age, occupation
from employees;
However, your data structure is suspect. Either you should use a flag in employees to identify the "VIP employees". Or you should have a primary key in employees and use this primary key in vip_employees to refer to employees. Copying over the data fields is rarely the right thing to do, especially for columns such as age which are going to change over time. Speaking of that, you normally derive age from the date of birth, rather than storing it directly in a table.
INSERT INTO studies
(
id
,name_string
,description
,field
,is_active
,register_start
,register_end
)
SELECT nextval('studiesSequence')
,NAME
,''
,3
,0
,register_start
,register_end
FROM dblink('dbname=mydb', 'select name,begins,ends from study')
AS t1(NAME VARCHAR(50), register_start DATE, register_end DATE);
You can directly insert values that retured by dblink()(that means no need to create a view)
Loop and cursor are weapons of last resort. Try to avoid them. You probably want INSERT INTO ... SELECT:
INSERT INTO x(x, y, z)
SELECT x, y, z
FROM t;
SqlFiddleDemo
EDIT:
INSERT INTO vip_employees(name, age, occupation) -- your column list may vary
SELECT name, age, occupation
FROM employees;
Your syntax is wrong. You cannot have both, a values clause for constant values and a select clause for a query in your INSERT statement.
You'd have to select constant values in your query:
insert into studies
(
id,
name_string,
description,
field,
is_active,
register_start,
register_end
)
select
studiesSequence.nextval,
name,
'Test',
null,
0,
register_start,
register_end
from old_study;