query in sql server for retrieving rows - sql

I have a table that contains the following 4 columns:
id
name
lastname
phone
I want to write a stored procedure that gets an id as parameter, and then gets the name of that id and then use that name to get all the rows that their name is equal to the names that i found in last step!
here it is my query, i know it's wrong but i'm new to sql commands:
ALTER PROCEDURE dbo.GetAllNames
#id int
AS
select name as Name from Users where id = #id
-- i don't how to retrieve the names that are equal to Name
select * from Users where name = Name
can you correct my query and help me? Thanks.

SELECT by_name.name FROM Users AS by_id
join Users AS by_name ON by_id.name = by_name.name
where id = #id

You can simply say
SELECT * FROM users WHERE name in (SELECT name from users where id = #id)
This would handle the case where there are multiple records with the ID. If ID is a primary key, then you can replace the IN operator with =.

Try this :
ALTER PROCEDURE dbo.GetAllNames
#Id INT
AS
BEGIN
SELECT * FROM Users WHERE [Name] IN (SELECT [Name] FROM Users WHERE Id = #Id)
END

You can declare a variable #name where you can store the name....
ALTER PROCEDURE dbo.GetAllNames
#id int
AS
DECLARE #name nvarchar(50);
select #name =name from Users where id = #id;
select * from Users where name = #name;
I have just provide above solution as per your question style but I strongly recommend you to use JOIN in given scenario in following way:
SELECT b.name FROM Users a
INNER JOIN Users b
ON a.name = b.name
WHERE a.id = #id

Related

SQL Stored procedure querying multiple tables syntax

I am currently trying to create a stored procedure where it first grabs the RUId(Registered User ID) from the first table.And then uses this variable to query another table
The easiest way to explain this is by showing the a pseudo code of this request as shown below
create procedure GetRUIdForUser
#Email nvarchar (160)
AS
SELECT RUId From RegisteredUsers
WHERE Email = #Email
Then
Select * From OtherTable where Ruid = #Ruid
What would the correct syntax for this be or would this need to be split up into two separate stored procedures?
Thanks!
Why not simply use JOIN ? instead of multiple variable & select statements :
select t.*
from RegisteredUsers ru inner join
table t
on t.Ruid = ru.RUId
where ru.Email = #Email;
However, your query variable will have only one ruid which will not help you more. So, you need a table variable to hold all ruids instead.
Try this:
SELECT *
FROM OtherTable
WHERE Ruid = ( SELECT RUId
FROM RegisteredUsers
WHERE Email = #Email ) ;
I recommend a join but you need to declare a variable to use what you are trying to do.
create procedure GetRUIdForUser #Email nvarchar (160) as
declare #ruid int
SELECT #ruid = RUId From RegisteredUsers
WHERE Email = #Email
Select * From OtherTable where Ruid = #Ruid
My guess is that problem isn't as simple as you summarized.

SQL Server Stored Procedure Check if Record Exists Before Insert

I am doing a check to see if a record exists before inserting it into a table (and this method seems to work on other stored procedures I am already using) but for this particular stored procedure it is not inserting anything even though the table is empty, why not?
CREATE PROCEDURE spInsertMovieHasTrailer
#movieID int,
#name varchar(50)
AS
BEGIN
SELECT #name = name, #movieID = movieID
FROM MovieHasTrailer
WHERE name = #name and movieID = #movieID
IF #name IS NULL and #movieID IS NULL
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
#movieID,
#name
)
END
END
Executing like this:
execute spInsertMovieHasTrailer 1, 'Test'
I would build this directly into the insert and not use if logic. if introduces race conditions:
INSERT INTO MovieHasTrailer
SELECT movieID, name
FROM (SELECT #movieID as movieID, #name as name) t
WHERE NOT EXISTS (SELECT 1
FROM MovieHasTrailer mht
WHERE mht.MovieId = t.MovieID AND mht.name = t.name
);
Note that this assumes that you need both the id and name to match the movie. I would think the id would be sufficient.
Also, what I would really do is have a unique index on either MovieHasTrailer(MovieId) or MovieHasTrailer(MovieId, Name). Then use a try/catch block if there is an insert error.
your select into variable may returns more than one value and you get error, it's better to use if not exists:
IF NOT EXISTS
(
SELECT name, movieID
FROM MovieHasTrailer
WHERE name = #name and movieID = #movieID
)
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
#movieID,
#name
)
END
The reason you are not doing an insert is the following code will not change the value of #name and #movieID if the query returns no records
SELECT #name = name, #movieID = movieID
FROM MovieHasTrailer
WHERE name = #name and movieID = #movieID
Whatever value for #name and #movieID you are passing into the stored procedure remain unchanged. I assume you are not passing in null values so the IF block is never executed.
You can try this way also you can achieve your goal and it save your time also.
INSERT INTO MovieHasTrailer
SELECT #movieID as movieID, #name as name
except
select MovieId, name
FROM MovieHasTrailer mht
where MovieId = #MoveID
I would do this by standart MERGE statement:
Create table t(id int, name nvarchar(max))
Declare #id int = 1, #name nvarchar(max) = 'Mission imposible'
Merge t using (select #id, #name) as s(id, name)
on t.id = s.id
when not matched then
insert(id, name) values(s.id, s.name);
You can also add WHEN MATCHED THEN UPDATE, WHEN NOT MATCHED BY SOURCE THEN DELETE to this statement.
Fiddle: http://sqlfiddle.com/#!6/c2569/23
try this :
CREATE PROCEDURE spInsertMovieHasTrailer
#movieID int,
#name varchar(50)
AS
BEGIN
declare #rowStatus nvarchar(50)=null
set #rowStatus=(SELECT name FROM MovieHasTrailer WHERE name = #name and movieID = #movieID)
IF (#rowStatus is NULL)
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
#movieID,
#name
)
END
END

How to return default value from SQL query

Is there any easy way to return single scalar or default value if query doesn't return any row?
At this moment I have something like this code example:
IF (EXISTS (SELECT * FROM Users WHERE Id = #UserId))
SELECT Name FROM Users WHERE Id = #UserId
ELSE
--default value
SELECT 'John Doe'
How to do that in better way without using IF-ELSE?
Assuming the name is not nullable and that Id is unique so can match at most one row.
SELECT
ISNULL(MAX(Name),'John Doe')
FROM
Users
WHERE
Id = #UserId
Try ISNULL or COALESCE:
SELECT ISNULL((SELECT TOP 1 Name FROM Users WHERE Id = #UserId), 'John Doe')
The inner select will return nothing if no user exist with this id, the isnull will solve this case.
Try this
SELECT IFNULL(Name,'John Doe')
FROM Users
WHERE Id = #UserId)
You can drop the if statement using following construct but that doesn't necessarely mean it is better.
SELECT Name FROM Users WHERE Id = #UserId UNION ALL
SELECT 'John Doe' WHERE NOT EXISTS (SELECT Name FROM Users WHERE Id = #UserId)
Try isnull
SELECT IsNULL(Name, 'John Doe') FROM Users WHERE Id = #UserId
Edit:
drop table users
go
create table users
(id int,name varchar(20))
go
insert into users select 1,'1'
go
declare #userid int
set #userid = 1
select isnull(username.username, 'John Doe')
from (select #userid as userid) userid
outer apply (SELECT name as username FROM Users WHERE Id = userid.userid ) username
--outer apply (SELECT name as username FROM Users WHERE Id = #userid ) username
I suppose you could use ##ROWCOUNT to see if any will be returned.
SELECT Name FROM Users WHERE Id = #UserId
if(##ROWCOUNT = 0)
SELECT 'John Doe'
You could also use a variable if you're expecting one row.
declare #name varchar(100)
set #name = (select top 1 name from users where id = #userId)
if(#name is null) set #name = 'John Doe'
select #name
I would suggest that the best way to do is that first declare #name . Then set this value based on user id and then if #name is null show default name otherwise show name... That method would be as efficient as any other method and will be more readable.for other methods any other user to have think a lot to know what is going on unless there is nice comment.
declare #userid int
set #userid = 1
select isnull(
(select name from users where id = #userid),
'John Doe'
)
go
--My preffered would be this one..
declare #name varchar(20),#userid int
set #userid = 1
select #name = name from users where id = #userid
select isnull(#name,'John Doe')
If the query is supposed to return at most one row, use a union with the default value then a limit:
SELECT * FROM
(
SELECT Name FROM Users WHERE Id = #UserId`
UNION
SELECT 'John Doe' AS Name --Default value
) AS subquery
LIMIT 1
Both the query and default can have as many columns as you wish, and you do not need to guarantee they are not null.

sql to nhibernate

I need to convert this SQL query to nhibernate
declare #i int set #i=2
while (#i>0)
begin
insert into #tmp_table3 (id , descr , RangeType , createdate )
select * from AgeRanges as ar where AgeRangeID in (
select AgeRangeID as id from AgeRangeDetails where agerangeid in
(select AgeRangeID from agerangedetails group by AgeRangeID having COUNT(AgeRangeID)=2)
and agestart =(select AgeStart from #tmp_table2 where id=#i)
and AgeEnd = (select AgeEnd from #tmp_table2 where id=#i)
and Payment = (select Payment from #tmp_table2 where id=#i)
group by AgeRangeID)
and AgeRangeType=0
and AgeRangeID<>5
set #i=#i-1
end
select id from #tmp_table3 where id in
(select id from #tmp_table3 group by id having COUNT(id)=2) group by id
can someone help me to do this.
thanks
This is quite a custom bit of SQL, it has a while loop, tmp tables and variables. For this reason you are only going to be able to either create a Stored Procedure or use a named query.
a) create a Stored procedure and call it using:-
session.CreateSqlQuery("exe sp_name")...
more details...
b) create a named query in mapping and call it like this:-
session.GetNamedQuery("MyNamedQuery")...
more details...

SQL if( exists()) query duplication

I need to write a a query that gets a set of information from a table, but if there is no information for that specific client, then use the default set. I was wondering if there is a way to avoid query duplication in an if(exists()) statement.
For example:
IF( EXISTS( SELECT * FROM UserTable WHERE Name = #UserName))
BEGIN
SELECT * FROM UserTable WHERE Name = #UserName))
END
ELSE
BEGIN
SELECT * FROM UserTable WHERE Name = 'Jon Skeet'))
END
The first two selects (exists and the true part of the if) are the exact same. I want to avoid running the same query twice if the statement is true. I know the exists stops once the first true condition is met but that is still O(n) worst case.
Another option I know of, is put the information in a temp table and check if information is there, if not return the default information.
Both ways would work but what is the best way to do it? Are there other ways to do this? Is there some way to do this in the WHERE clause since that's the only thing that is different?
Edit: Fixed example to return a row not just a single item. So the answers of dumping the select to a single variable would be equal to a temp table I assume. Also, to not anger Jon Skeet, spelled his name right
You could do this:
SELECT TOP 1
UserID
FROM
UserTable
WHERE
Name IN (#UserName, 'John Skeet')
ORDER BY
CASE WHEN Name = 'John Skeet' THEN 2 ELSE 1 END
(or use LIMIT or whatever the method is for your RDBMS)
Or you could do this:
DECLARE #UserID INT
SELECT
#UserID = UserID
FROM
UserTable
WHERE
Name = #UserName
IF (#UserID IS NULL)
SELECT
#UserID = UserID
FROM
UserTable
WHERE
Name = 'John Skeet'
SELECT #UserID AS UserID
Or this:
SELECT
COALESCE(T2.UserID, T1.UserID)
FROM
UserTable T1
LEFT OUTER JOIN UserTable T2 ON
T2.Name = #UserName
WHERE
T1.Name = 'John Skeet'
Or this:
SELECT
UserID
FROM
UserTable
WHERE
Name = #UserName
IF (##ROWCOUNT = 0) -- MS SQL Server specific, your RDBMS method will vary
SELECT
UserID
FROM
UserTable
WHERE
Name = 'John Skeet'
How about:
DECLARE #UserID int;
SELECT #UserID = UserID FROM UserTable WHERE Name = #UserName
IF(#UserID IS NULL)
BEGIN
SELECT #UserID=UserID FROM UserTable WHERE Name = 'Jon Skeet'))
END
SELECT #UserID
You can select into a variable check the variable if it comes back null run the get default query
something like this:
Declare #uID int;
SELECT #uID = UserID FROM UserTable WHERE Name = #UserName
IF (#uID is null)
begin
'Select default here'
End
select #uID
If you are concerned about performance, I think you probably don't need to be - most DBMSes should optimize away the duplication. If you are still concerned about performance, run it both ways to see if your DBMS has any problem with it.
If you're concerned about code - maintainability of duplicate code sections, readability, and the like, then study the above answers with that in mind. You may find that the duplication is your least-worst option. It's a shame SQL isn't more malleable.
You don't say what DBMS you are using, but it clearly isn't Oracle (which is the one I know). However, I would expect your DBMS would allow you to do something like this pseudo-code:
SELECT UserID FROM UserTable WHERE Name = #UserName
IF <no data returned by that>
BEGIN
SELECT UserID FROM UserTable WHERE Name = 'John Skeet'
END
In Oracle this would be:
BEGIN
SELECT UserID INTO v_UserID FROM UserTable WHERE Name = :UserName;
EXCEPTION
WHEN NO_DATA_FOUND THEN
SELECT UserID INTO v_UserID FROM UserTable WHERE Name = 'John Skeet';
END
Unless you are going to define a set of variables for each field you are returning (and it's only one record) I think the most efficent way is to make the call twice. The temp table would probably cost more.