Select and assign to variable in one statement? - sql

I'd like to display the results of a query, and I'd like to capture a column's value at the same time. The FROM and WHERE are the same in both queries. Can I do both in one query, or is it easier/better to just do the query twice, like this?
DECLARE #fooId INT
SET #fooId = (SELECT FooId FROM Bar WHERE SnuhId = 5)
SELECT * FROM Bar WHERE SnuhId = 5

Unfortunately it has to be done in two operations.
Test:
DECLARE #VAR DATETIME
SELECT #VAR=GETDATE(), GETDATE()
Yields error message 141.
Here's another SO post on this.

If you try to do it in one query, you will get an error msg - A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
To avoid this, the possibilities are
1) Make sure that all columns are assigned to a local variable. Ex
DECLARE #fooId INT
DECLARE #barId INT
SELECT #fooId = FooId, #barId = BarId FROM Bar WHERE SnuhId = 5
2) simply remove '*' from the SELECT statement
SELECT #fooId = FooId, BarId FROM Bar WHERE SnuhId = 5 //remove BarId column from this query
3) If you really need to do both, meaning to assign the value to local variables and to return the columns as a result set, you have to do it in 2 steps instead of combining them into one SELECT statement.

You can do the following to reduce one line:
DECLARE #fooI INT
SET #fooId = (SELECT FooId FROM Bar WHERE SnuhId = 5)
SELECT #fooId as [FooId]
It will reduce unnecessary replication of your query.
I hope this helps.

Related

Anything like template literals while writing a search query in SQL?

I am writing a stored procedure to get a particular value.
declare #num int
set #num = (SELECT Id
FROM [sometable]
WHERE Name like '%today%')
-- returns #num = 1
Select Value
FROM [anothertable]
where name like 'days1'
In the last line of the query I want to add "1" or any other number after 'days', depending on the variable #num.
How can I do it, sort of like how we use template literals in Javascript, using the ${} syntax but in SQL?
You can just use the first query as a sub-query of the second:
select [Value]
from anothertable
where [name] = Concat('days', (select Id from sometable where [Name] like '%today%'));

Set int var value as wildcard

I've looked into this and I'm just struggling to accept that it isn't possible to do.
I write queries for others to use and normally include some declared variables at the top so the user can "filter" their search at the top of the query and not bother with the rest.
Sometimes the user may not want to specify the values for a particular variable, as they want to return all types. I know this isn't what SQL is for and that there are reporting tools. Any suggestions on how to do this?
DECLARE #foo int, #bar bit
SET #foo = *
SET #bar = *
SELECT *
FROM table
WHERE foo = #foo
AND bar = #bar
* isn't a valid int value and even if an int value could be used as a wildcard, you would need to use LIKE not =.
What you want here is a NULL value and the proper boolean logic.
SELECT {Columns}
FROM [Table]
WHERE (foo = #foo OR #foo IS NULL)
AND (bar = #bar OR #bar IS NULL)
OPTION (RECOMPILE);-- Comment out/remove if you aren't using T-sQL due to incorrect tagging

Replace Any Occurrence of "P" in String With A Value From Another Table

I have a column, sort_order in a table that contains a string of numbers, a delimiter and some P values:
1150||P||1168||1144||1149||1147||1164||1152||P||1148||1162||1163||P||1156||1157||1154||
I would like to replace any P values in this string with another value from the event_tile_id column of another table.
So far I've drafted this SQL below with no luck. What changes can I make to this Query to get the effect I need?
`SELECT sort_order,
(
REPLACE(sort_order,'P',
(SELECT TOP 1 event_tile_id
FROM daily_email_sales_today)
)
)
as sort_order
FROM daily_email_preview`
Removed "default_SaleID" from Query. Replace should now have 4 arguments.
This is how I would do it.
Since you don't have any joins, why not do a simpler update query using a static value?
DECLARE #update VARCHAR(100)
SET #update = (SELECT TOP 1 event_tile_id FROM daily_email_sales_today)
update daily_email_preview
SET sort_order = replace(sort_order,'P', #update)
Or even,
update daily_email_preview
SET sort_order = replace(sort_order,'P', '<new value>')
Assuming you are using SQL Server.
Along the same thought process as #Eric_Hauenstein if you are running this in a TSQL process:
declare #rSTR as varchar(50)
SELECT TOP 1 #rSTR = event_tile_id FROM daily_email_sales_toda
SELECT sort_order, REPLACE(sort_order,'P', #rSTR) as sort_order
FROM daily_email_preview

Set a parameter in select statement

I am trying to set a parameter in the select statement and then pass it to a user defined function in the same statement. Is this possible? If yes, where is my mistake? If no, then I guess I will have to write a cursor and some temporary tables which I want to avoid.
declare #param varchar(1000)
select Pincode, Name,( #param = AlternateName) as AlternateName
,(select Top(1) part from SDF_SplitString (#param,',')) as NewName from PinCodeTable
You can either get all of the fields out as variables, or get the usual set of rows, but you can't mix and match in a single SELECT. Variables are limited to queries that return no more than one row. (Why do I feel like I'm about to learn something frightening?)
If you are writing a stored procedure and doing something like header/trailer rowsets, you can always return a rowset built from variables:
SELECT #Foo = Foo, #Bar = Bar, ... from Headers where Id = 42
SELECT #Foo as Foo -- Return the first rowset.
SELECT Size, Weight, Color from Trailers where Bar = #Bar -- Return second rowset.

SQL: Order randomly when inserting objects to a table

I have an UDF that selects top 6 objects from a table (with a union - code below) and inserts it into another table. (btw SQL 2005)
So I paste the UDF below and what the code does is:
selects objects for a specific city and add a level to those (from table Europe)
union that selection with a selection from the same table for objects that are from the same country and add a level to those
From the union, selection is made to get top 6 objects, order by level, so the objects from the same city will be first, and if there aren't any available, then objects from the same country will be returned from the selection.
And my problem is, that I want to make a random selection to get random objects from table Europe, but because I insert the result of my selection into a table, I can't use order by newid() or rand() function because they are time-dependent, so I get the following errors:
Invalid use of side-effecting or time-dependent operator in 'newid' within a function.
Invalid use of side-effecting or time-dependent operator in 'rand' within a function.
UDF:
ALTER FUNCTION [dbo].[Objects] (#id uniqueidentifier)
RETURNS #objects TABLE
(
ObjectId uniqueidentifier NOT NULL,
InternalId uniqueidentifier NOT NULL
)
AS
BEGIN
declare #city varchar(50)
declare #country int
select #city = city,
#country = country
from Europe
where internalId = #id
insert #objects
select #id, internalId from
(
select distinct top 6 [level], internalId from
(
select top 6 1 as [level], internalId
from Europe N4
where N4.city = #city
and N4.internalId != #id
union select top 6 2 as [level], internalId
from Europe N5
where N5.countryId = #country
and N5.internalId != #id
) as selection_1
order by [level]
) as selection_2
return
END
If you have fresh ideas, please share them with me.
(Just please, don't suggest to order by newid() or to add a column rand() with seed DateTime (by ms or sthg), because that won't work.)
Perhaps you could take advantage of the guids by adding a position parameter to your inputs and then passing in a randomly generated value and then ordering by Substring(internalID, #Random,1)
I found a good solution myself and I thought it might be handy to share it :)
DECLARE #seed1 int
DECLARE #seed2 int
SET #seed1 = DATEPART(SECOND,GETDATE())
SET #seed2 = DATEPART(MILLISECOND,GETDATE())
SELECT TOP 10 [Column1], [Column2]
FROM [TABLE]
ORDER BY ROW_NUMBER() OVER (ORDER BY [KeyColumn]) * seed2 % seed1
I think it's simple enough and it's quite handy
What version of the database server are you using?
In SQL Server 2005 you can use rand with getdate as seed, and the function becomes indeterministic.
In earlier versions you can't have indeterministic functions, and you would have to use a stored procedure instead.