sql insert into table which uses newid in user defined function [duplicate] - sql

I have to insert a fake column at the result of a query, which is the return value of a table-value function. This column data type must be unique-identifier. The best way (I think...) is to use newid() function. The problem is, I can't use newid() inside this type of function:
Invalid use of side-effecting or time-dependent operator in 'newid()' within a function.

here's a clever solution:
create view getNewID as select newid() as new_id
create function myfunction ()
returns uniqueidentifier
as begin
return (select new_id from getNewID)
end
that i can't take credit for. i found it here:
http://omnibuzz-sql.blogspot.com/2006/07/accessing-non-deterministic-functions.html
-don

You can pass NEWID() as a parameter to your function.
CREATE FUNCTION SOMEIDFUNCTION
(
#NEWID1 as varchar(36), #NEWID2 as varchar(36)
)
RETURNS varchar(18)
AS
BEGIN
-- Do something --
DECLARE #SFID varchar(18)
SELECT #SFID = 'DYN0000000' + LOWER(LEFT(#NEWID1,4)) + LEFT(#NEWID2,4)
RETURN #SFID
END
GO
Call the function like this;
SELECT dbo.SOMEIDFUNCTION(NewID(),NewID())

use it as a default instead
create table test(id uniqueidentifier default newsequentialid(),id2 int)
insert test(id2) values(1)
select * from test
NB I used newsequentialid() instead of newid() since newid() will cause pagesplits since it is not sequential, see here: Some Simple Code To Show The Difference Between Newid And Newsequentialid

You could use ROW_NUMBER function:
SELECT
(ROW_NUMBER() OVER (ORDER BY recordID) ) as RowNumber ,
recordID,
fieldBla1
FROM tableName
Find more information at http://msdn.microsoft.com/pt-br/library/ms186734.aspx

Related

How to select from text list randomly?

I'm trying to build SQL function that I can use as a default value for a column. The function is about selecting an avatar image path randomly if the user didn't assign an image.
I have tried to but a completely wrong example to just approach the image not the solution
what I need to do is something like this
select top 1 from "avatar1,png, avatar2,png, avatar3.png, avatar4.png, avatar5.png" order by rand();
and I will convert it to a function like this
CREATE FUNCTION dbo.ReturnAvatar()
RETURNS nvarchar(100)
AS
BEGIN
DECLARE #ret nvarchar(100);
SET #ret = (select top 1 from "avatar1,png, avatar2,png, avatar3.png, avatar4.png, avatar5.png" as tbl order by rand());
RETURN #ret;
END;
this is just to explain the idea that I'm not able to apply. I don't know if SQL server has something like this or not.
Here is one way:
CREATE VIEW getNewID AS SELECT newid() as new_id
CREATE FUNCTION dbo.ReturnAvatar()
RETURNS nvarchar(100)
AS
BEGIN
DECLARE #ret nvarchar(100);
SET #ret = (SELECT TOP 1 value
FROM
STRING_SPLIT('avatar1.png,avatar2.png,avatar3.png,avatar4.png,avatar5.png', ',')
ORDER BY (SELECT new_id FROM getNewID));
RETURN #ret;
END;
Note that your current CSV string of filenames does not seem proper, because comma does not indicate the start of the extension in either Windows or Linux. So, I have assumed dot everywhere. In addition, if you want to use STRING_SPLIT, you may only split on a single character. Therefore, I assume that comma will be the delimiter here.
You do not need to create a table at all. Simply put the number inside your string and choose the number randomly:
select 'avatar'+str(round(rand()*5+1,0))+'.png'
would be fine.
Put that into your function and you are all set.
rand() produces 0..1(excl.) so you can simply multiply it by 5 and add 1 to get your range of 1...5
Demo: http://sqlfiddle.com/#!18/9eecb/82866
Documentation:
ROUND ( numeric_expression , length [ ,function ] )
STR ( float_expression [, length [, decimal]])
rand(seed)
So essentially you could boil it down to:
select 'avatar'+ltrim(str(rand()*5+1,20,0))+'.png'
with
ltrim(string) taking care of the space
create function dbo.ReturnAvatar(#uid uniqueidentifier, #avatars int = 10)
returns varchar(100)
as
begin
return ('avatar' + cast(abs(checksum(#uid)) % isnull(abs(#avatars), 10)+1 as varchar(100)) + '.png')
end
go
create table myusers
(
username varchar(50),
theavatar varchar(100) default( dbo.ReturnAvatar(newid(), default))
);
insert into myusers(username)
select top (10000) 'user' + cast(row_number() over(order by(select null)) as varchar(50))
from master.dbo.spt_values as a
cross join master.dbo.spt_values as b;
go
select theavatar, count(*)
from myusers
group by theavatar;
go
drop table myusers;

Is there any way to convert varchar to int value in sql?

I have a query like this when I pass the values into in operator in sql it shows:
Conversion failed when converting the varchar value '3,4,9' to data type int.
How can I solve the issue?
declare #values varchar(100)
set #values = '3,4,9'
select #values
select * from CmnItemType where ItemTypeID in (#values)
No. You can use string_split() or a similar user-defined function:
where itemtypeid in (select try_convert(int, value) from string_split(#values))
What I usually do is use table variable, like this one:
DECLARE #values TABLE (id INT)
INSERT INTO #values (id) VALUES (3),(4),(9)
SELECT id FROM #values
From that, you could simply do a join to your tables.
If you are creating a stored procedure, you can use a TVP to pass parameters, here is the Microsoft doc on that. With a TVP, your code can simply call your SP with a list and you will be able to join it in the SP.
Hope this will help.

Passing multiple values to a parameter of a function in SQL

There is function Getfunctionname(userid, startdate, enddate) to return a table
My question is can I pass a variable with multiple values?
i.e.
getfunctionname(#userid, startdate, enddate)
Where the value of variable #userid is like
1
2
3
4
5
(actually using split function splitting the values from being 1,2,3,4,5 )
If I can please let me know
One way of doing that which I prefer is to make a new user-defined table data type.
CREATE TYPE [dbo].[IdList] AS TABLE(
[Id] [int] NULL
)
Then you can use that data type as one of the parameters
CREATE FUNCTION Getfunctionname
(
#UserIDs dbo.IdList READONLY,
#startdate INT,
#endtdate INT
)
RETURNS #ReturnTable TABLE
(
-- ReturnTable
)
AS
BEGIN
-- Query
RETURN
END
Use the concept of CSV
CREATE FUNCTION [dbo].[uspGetNumbers]
userid,startdate,enddate // define your paramters the way you want
AS
BEGIN
// your code
JOIN dbo.fnSplit(#UserIDs, ',')
END
GO
Example function:
SELECT [dbo].[uspGetNumbers] '1,2,3,4,5', '', ''
I just ran into this, and I used the CROSS APPLY solution from this post:
SQL Server: run function for each row based on the provided row value
To use CROSS APPLY, you would need to first select your values, and then CROSS APPLY. I have not used the split function before, so I don't have the exact syntax,
but if you use it something like:
select #userid, F1.* from split(1,2,3,4,5),
CROSS APPLY getfunctionname(#userid, startdate, enddate) F1

Multiple values in a single parameter of a scalar function

Is there a way to input multiple values in a single parameter of a scalar-valued function in SQL Server 2008 R2 and have it filter data by that parameter using both values?
For example I would like to do the following
SET #Salesperson='BILL' OR 'MOSES'
SELECT Sum(SalesDollars)
FROM Invoices
WHERE Invoices.Salesperson = #Salesperson
I attempted to use the following as the WHERE clause, but this didnt work either.
SET #Salesperson='BILL','MOSES'
SELECT Sum(SalesDollars)
FROM Invoices
WHERE Invoices.Salesperson IN (#Salesperson)
Would it be easier if i were dealing with integers as opposed to varchar values?
Any help would be absolutely appreciated!
You need to use table-valued parameters. Look it up on technet or msdn
Best part of it that your table-valued parameters can have multiple columns.
Note however that you have to define TVP parameter as readonly. So if you want to return similar set from your function you will need to create another variable inside your function.
Example:
CREATE TYPE Names AS TABLE
( Name VARCHAR(50));
GO
/* Create a procedure to receive data for the table-valued parameter. */
CREATE PROCEDURE dbo.mySP
#n Names READONLY
AS
SELECT Sum(SalesDollars)
FROM
WHERE Invoices.Salesperson in (select Name from #n)
GO
CREATE FUNCTION dbo.myFun(#n Names READONLY) returns int
AS
SELECT Sum(SalesDollars)
FROM
WHERE Invoices.Salesperson in (select Name from #n)
GO
/* Declare a variable that references the type. */
DECLARE #names AS Names;
/* Add data to the table variable. */
INSERT INTO #names (Name)
VALUES ('BILL'),('MOSES')
-- using stored procedure with TVP
EXEC dbo.mySP #names
-- using function with TVP
select dbo.myFun(#names)
GO
This could be done this way:
SET #Salesperson='BILL,MOSES'
SELECT *
FROM YourTable
WHERE Invoices.Salesperson IN (SELECT * FROM dbo.split(#Salesperson,','))
This is how you split the values.
I would typically do this using a user defined table type: SQL Fiddle Example.
CREATE TYPE <schema>.SalespersonList AS TABLE
(
Name varchar(32)
)
You may have to grant execute permissions on the type:
GRANT EXECUTE ON TYPE::<schema>.SalespersonList TO <user>
Then you can create a function to use it:
CREATE FUNCTION <schema>.fnGetTotalSales
(
#nameList <schema>.SalespersonList READONLY
)
RETURNS INT
AS
BEGIN
DECLARE #ret INT
SELECT #ret = Sum(SalesDollars)
FROM Invoices i
INNER JOIN #nameList nl ON nl.Name = i.Salesperson
RETURN #ret
END
Then you would just insert your list into the type and call the function:
DECLARE #salesPersonList <schema>.SalespersonList
INSERT INTO #salesPersonList (Name)
SELECT 'Bill'
UNION
SELECT 'Moses'
SELECT <schema>.fnGetTotalSales(#salesPersonList)

SQL - create function that will take a table variable as an input

I'm having trouble writing a function that will take a table variable as an input and return the total number of rows in that table.
Here is my try:
CREATE FUNCTION fTableRows( #table TABLE )
RETURNS INT AS
BEGIN
RETURN( SELECT COUNT(*) FROM #table )
END
If you do this in SQL server 2008 + you have use user defined data type - table.
Good explanation can be found here: Pass table as parameter into SQL Udf
CREATE FUNCTION getTableRows
(
#TableName VARCHAR(30)
)
RETURNS INT AS
BEGIN
RETURN( SELECT COUNT(*) FROM #TableName)
END