Why is my function name ambiguous? It is not imho? - sql

Please consider the following function and function call:
create function [dbo].[GetCidrIpRange2](#CidrIp varchar(15))
returns #result table
(
LowRange varchar(15) not null,
HighRange varchar(15) not null,
AddressQty bigint not null
)
as
begin
declare #Base bigint = cast(4294967295 as bigint)
declare #Mask int = cast(substring(#CidrIp, patindex('%/%' , #CidrIP) + 1, 2) as int)
declare #Power bigint = Power(2.0, 32.0 - #Mask) - 1
declare #LowRange bigint = dbo.[IPAddressToInteger](left(#CidrIp, patindex('%/%' , #CidrIp) - 1)) & (#Base ^ #Power)
declare #HighRange bigint = #LowRange + #Power
insert #result
select
LowRange = #LowRange
,HighRange = #HighRange
,AddressQty = convert(bigint, power(2.0, (32.0 - #Mask)))
return
end
select [dbo].[GetCidrIpRange2]('195.65.254.11/2');
I get the following error:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.GetCidrIpRange2", or the name is ambiguous.
The name is unique, and when I run only the function, it created the function properly in the session:
Command(s) completed successfully.
What am I doing wrong?

You are missing a FROM:
SELECT * FROM [dbo].[GetCidrIpRange2]('195.65.254.11/2');

Related

How to assign column name to return value of scalar function in sql serve

I have defined a function in sql function, that inputs 3 names (three varchars) and outputs one name (one varchar)'. What I only want to is to give this return value a name/column name.
Right now when I call my function:
select concat_names(#first_name, #middle_name,#last_name)
I see returned varchar with no column name.
Here is complete code:
if object_id('[co1].[concat_names]') is not null
drop function [co1].[concat_names];
go
create function [co1].[concat_names]
(
#first_name varchar(20),
#middle_name varchar(20),
#last_name varchar(20)
)
returns varchar(62)
as
begin
declare #full_name varchar(62)
set #full_name = #first_name;
if(#middle_name is not null)
set #full_name = #full_name + ' ' + #middle_name;
if(#last_name is not null)
set #full_name = #full_name + ' ' + #last_name;
return #full_name;
end
go
When I do:
select concat_names('A', 'B', 'C')
I get no column name in result set.
I know I can rename the column name after its returned as no column name in above select query.
What I only want to know, if there is any way I can name the column while returning the value from the
Try this:
select fullname(#fn, #mn,#ln) AS 'yourName'
You can create table value function to return column with name, like this exmple:
create function udf_ParseDate (
#date as datetime
) returns #dateinfo table (
id int identity(1,1),
[date] datetime,
[year] int,
[month] smallint,
[day] smallint
)
as
begin
insert into #dateinfo
select #date, YEAR(#date), MONTH(#date), DAY(#date)
return;
end
In your code:
if object_id('[co1].[concat_names]') is not null
drop function [co1].[concat_names];
go
create function [co1].[concat_names]
(
#first_name varchar(20),
#middle_name varchar(20),
#last_name varchar(20)
)
returns returns #info table (
fullName varchar(256)
)
as
begin
declare #full_name varchar(62)
set #full_name = #first_name;
if(#middle_name is not null)
set #full_name = #full_name + ' ' + #middle_name;
if(#last_name is not null)
set #full_name = #full_name + ' ' + #last_name;
insert into #info select #full_name;
return;
end
go
Do this:
SELECT fullname(#fn, #mn,#ln) AS COLUM_NAME_YOU_WANT
Create your function something like this:
create function concatall (
#fn as TEXT,
#mn as TEXT,
#ln as TEXT
) returns #merged table (
[FullName] TEXT
)
as
begin
insert into #merged
SELECT CONCAT(#fn , #mn , #ln)
return;
end
What you are looking for is not possible in SQL Server for Scalar valued Functions. Even the default SQL Server Scalar valued function return data with (No column name)
For example
select Checksum('somedata')
Output
(No column name)
---------------------
-1791257452
I am not sure why you want the column name to come from function if you can use alias name, what benifit you are getting?
If you just want to know it is possible or not, in that case answer is "NO".
Only option you have is to use alias name with AS like follwong.
SELECT fullname(#fn, #mn,#ln) AS FullName

What am I doing wrong in calculating cidr IP range?

I am trying to write a function that will output some address information on a CIDR formatted IP (output underneath code):
create function dbo.ConvertIpToInt (#Ip as varchar(15))
returns bigint
as
begin
return (convert(bigint, parsename(#Ip, 1)) +
convert(bigint, parsename(#Ip, 2)) * 256 +
convert(bigint, parsename(#Ip, 3)) * 256 * 256 +
convert(bigint, parsename(#Ip, 4)) * 256 * 256 * 256)
end
go
create function dbo.ConvertIntToIp (#Int bigint)
returns varchar(15)
as
begin
declare
#IpHex varchar(8)
,#IpDotted varchar(15)
select
#IpHex = substring(convert(varchar(30), master.dbo.fn_varbintohexstr(#Int)), 11, 8)
select
#IpDotted = convert(varchar(3), convert(int, (convert(varbinary, substring(#IpHex, 1, 2), 2)))) + '.' +
convert(varchar(3), convert(int, (convert(varbinary, substring(#IpHex, 3, 2), 2)))) + '.' +
convert(varchar(3), convert(int, (convert(varbinary, substring(#IpHex, 5, 2), 2)))) + '.' +
convert(varchar(3), convert(int, (convert(varbinary, substring(#IpHex, 7, 2), 2))))
return #IpDotted
end
go
create function dbo.GetCidrIpRange (#CidrIp varchar(15))
returns #result table
(
CidrIp varchar(15) not null,
Mask int not null,
LowRange varchar(15) not null,
LowIp varchar(15) not null,
HighRange varchar(15) not null,
HighIp varchar(15) not null,
AddressQty bigint not null
)
as
begin
declare #Base bigint = cast(4294967295 as bigint)
declare #Mask int = cast(substring(#CidrIp, patindex('%/%' , #CidrIP) + 1, 2) as int)
declare #Power bigint = Power(2.0, 32.0 - #Mask) - 1
declare #LowRange bigint = dbo.ConvertIpToInt(left(#CidrIp, patindex('%/%' , #CidrIp) - 1)) & (#Base ^ #Power)
declare #HighRange bigint = #LowRange + #Power
insert #result
select
CidrIp = #CidrIp
, Mask = #Mask
, LowRange = #LowRange
, LowIp = dbo.ConvertIntToIp(#LowRange)
, HighRange = #HighRange
, HighIp = dbo.ConvertIntToIp(#HighRange)
, AddressQty = convert(bigint, power(2.0, (32.0 - #Mask)))
return
end
go
select * from dbo.GetCidrIpRange('195.65.254.11/2');
This outputs the following:
CidrIp Mask LowRange LowIp HighRange HighIp AddressQty
--------------------------------------------------------------------------------------
195.65.254.11/2 2 3221225472 192.0.0.0 4294967295 255.255.255.255 1073741824
I have been browsing SO and Google for some hours now, and I am quite convinced that ConvertIpToInt and ConvertIntToIp are correct.
However, I was expecting the following output:
CidrIp Mask LowRange LowIp HighRange HighIp AddressQty
--------------------------------------------------------------------------------------
195.65.254.11/2 2 3275881985 195.65.254.1 3275882238 195.65.254.254 254
Can someone please point me out where the mistake in my code is? I've been staring myself blind and I don't see it (or I am misunderstanding how to do this).
According to both http://www.ipaddressguide.com/cidr and http://jodies.de/ipcalc?host=195.65.254.11&mask1=2&mask2=, your calculations are correct. The only disagreement between those two sites is that the jodies.de/ipcalc page removes the lowest and highest (broadcast) IP addresses from the range.
I tested with both 195.65.254.11/2 and 195.65.254.11/24. In order to get your code working, I needed to change the input parameter specification on dbo.GetCidrIpRang to be VARCHAR(20) (as mentioned by #Damien_The_Unbeliever in a comment on the question).
Two notes regarding performance:
For the ConvertIpToInt and ConvertIntToIp Scalar UDFs you might be better off using the INET_AddressToNumber and INET_NumberToAddress functions, respectively, that are included in the Free version of the SQL# SQLCLR library (which I wrote, but hey, Free :). The reason for this recommendation is that unlike T-SQL UDFs, deterministic SQLCLR UDFs (and these two are) do not prevent parallel plans.
If you don't want to go the SQLCLR route, then you should, at the very least, keep the ConvertIntToIp function as purely mathematical. There is no reason to do all of those conversions and substrings.
CREATE FUNCTION dbo.IPNumberToAddress(#IPNumber BIGINT)
RETURNS VARCHAR(15)
WITH SCHEMABINDING
AS
BEGIN
DECLARE #Oct1 BIGINT,
#Oct2 INT,
#Oct3 INT;
SET #Oct1 = #IPNumber / (256 * 256 * 256);
SET #IPNumber -= (#Oct1 * (256 * 256 * 256));
SET #Oct2 = #IPNumber / (256 * 256);
SET #IPNumber -= (#Oct2 * (256 * 256));
SET #Oct3 = #IPNumber / 256;
SET #IPNumber -= (#Oct3 * 256);
RETURN CONCAT(#Oct1, '.', #Oct2, '.', #Oct3, '.', #IPNumber);
END;
GO
And then:
SELECT dbo.IPNumberToAddress(3275881995);
-- 195.65.254.11
For the GetCidrIpRange TVF, you would be better off converting that to be an Inline TVF. You can accomplish the multi-step calculations via CTEs in the following manner (you will just need to clean it up a little / finish it):
WITH cte1 AS
(
SELECT 2 AS [Mask] -- replace with real formula
), cte2 AS
(
SELECT 999 AS [Base], -- replace with real formula
POWER(2.0, 32.0 - cte1.[Mask]) - 1 AS [Power],
cte1.[Mask]
FROM cte1
), cte3 AS
(
SELECT SQL#.INET_AddressToNumber(left(#CidrIp, PATINDEX('%/%' , #CidrIp) - 1))
& (cte2.[Base] ^ cte2.[Power]) AS [LowRange],
cte2.[Power],
cte2.[Mask]
FROM cte2
)
SELECT #CidrIp AS [CidrIp],
cte3.[Mask],
cte3.[LowRange],
SQL#.INET_NumberToAddress(cte3.[LowRange]) AS [LowIp],
(cte3.[LowRange] + cte3.[Power]) AS [HighRange],
SQL#.INET_NumberToAddress(cte3.[LowRange] + cte3.[Power]) AS [HighIp],
CONVERT(BIGINT, POWER(2.0, (32.0 - cte3.[Mask]))) AS [AddressQty]
FROM cte3 c;

Getting RGB(R,G,B) from ARGB integer (SQL)

I need to display some data in an SSRS 2008r2 report and the colors have to match a Windows VB app that saves it's colors as integers (e.g.16744703 is a pinkish color). I believe this is ARGB format. I'm not concerned about the alpha value, as the application does not allow the user to modify it.
I'm stuck on the SQL to convert ARGB to something compatible in SSRS. I need to do the translation in SQL as there are other factors that may override an objects color.
I can work with 3 ints for rgb or a hex value
Anyone got any idea how tot do this?
Regards
mark
Figured it out. Here's a function that returs either RGB() or Hex
-- Description: Converts ARGB to RGB(RR,GG,BB)
-- e.g. 16744703 returns RGB(255,128,255) or #FF80FF
CREATE FUNCTION [dbo].[ARGB2RGB]
(
#ARGB AS BIGINT
,#ColorType AS VARCHAR(1) -- 'H' = Hex, 'R' = RGB
)
RETURNS VARCHAR(16)
AS
BEGIN
DECLARE #Octet1 TINYINT
DECLARE #Octet2 TINYINT
DECLARE #Octet3 TINYINT
DECLARE #Octet4 TINYINT
DECLARE #RestOfColor BIGINT
SET #Octet1 = #ARGB / 16777216
SET #RestOfColor = #ARGB - ( #Octet1 * CAST(16777216 AS BIGINT) )
SET #Octet2 = #RestOfColor / 65536
SET #RestOfColor = #RestOfColor - ( #Octet2 * 65536 )
SET #Octet3 = #RestOfColor / 256
SET #Octet4 = #RestOfColor - ( #Octet3 * 256 )
RETURN
CASE #ColorType
WHEN 'R'
THEN 'RGB(' + CONVERT(VARCHAR, #Octet4) + ','
+ CONVERT(VARCHAR, #Octet3) + ',' + CONVERT(VARCHAR, #Octet2)
+ ')'
WHEN 'H'
THEN '#' + RIGHT(sys.fn_varbintohexstr(#Octet4), 2)
+ RIGHT(sys.fn_varbintohexstr(#Octet3), 2)
+ RIGHT(sys.fn_varbintohexstr(#Octet2), 2)
END
END
Hope someone else finds it useful
Regards
Mark
create FUNCTION [dbo].[ConvertRGB]
(
#ARGB AS float
)
RETURNS #ReturnValue TABLE ( R TINYINT,B TINYINT, G TINYINT )
as
BEGIN
DECLARE #testvarbinary binary(4)
DECLARE #strRBG nvarchar(MAX)
set #testvarbinary = CONVERT(binary(4),#ARGB)
set #strRBG=( SELECT substring(sys.fn_varbintohexstr(#testvarbinary),5,6))
DECLARE #temp AS TABLE (hex char(6))
INSERT INTO #temp
VALUES (#strRBG)
DECLARE #strHex AS varchar(16)
SET #strHex = '0123456789abcdef' -- Assuming case-insensitive collation!
INSERT INTO #ReturnValue
( R,G,B )
SELECT 16 * (CHARINDEX(SUBSTRING(hex, 1, 1), #strHex) - 1) + (CHARINDEX(SUBSTRING(hex, 2, 1), #strHex) - 1)
,16 * (CHARINDEX(SUBSTRING(hex, 3, 1), #strHex) - 1) + (CHARINDEX(SUBSTRING(hex, 4, 1), #strHex) - 1)
,16 * (CHARINDEX(SUBSTRING(hex, 5, 1), #strHex) - 1) + (CHARINDEX(SUBSTRING(hex, 6, 1), #strHex) - 1)
FROM #temp
RETURN
END;
GO
--select * from [ConvertRGB](10592513)
I was looking for doing something like this and came up with this post. It was of great help but I found it more appealing doing it inline as follow. Notice that the result can be used inside the SSRS Color Expression with no additional conversions
select CustomerID
,SSRSColor = '#' + SUBSTRING(S.TXTHEXColor, 5, 2)
+ SUBSTRING(S.TXTHEXColor, 3, 2)
+ SUBSTRING(S.TXTHEXColor, 1, 2)
from
(
Select CustomerID
,[TXTHEXColor] = right(sys.fn_varbintohexstr(CONVERT(varbinary, T.Color)), 6)
From SomeTable T
) S
If a function is still needed then following is a much shorter way but bear in mind that with big record sets functions can slow down the process a lot.
CREATE FUNCTION [dbo].[SSRSColor] (
#ARGB AS INT
)
RETURNS VARCHAR(7)
AS
BEGIN
DECLARE #TXTHEXColor varchar(100)
Select #TXTHEXColor = right(sys.fn_varbintohexstr(CONVERT(varbinary, #ARGB)), 6)
return '#' + SUBSTRING(#TXTHEXColor, 5, 2) + SUBSTRING(#TXTHEXColor, 3, 2) + SUBSTRING(#TXTHEXColor, 1, 2)
END

convert date to spanish in sql

I am running a report with multiple fields in english. I have 2 date fields at the end of the report, one has to be in English and the other in Spanish. The format the date needs to be in is ie November 1, 2012. I need the spanish to be Novembre 1, 2012. I cannot get the last field of the report to produce in spanish. I am running in sql server 2005.
Maybe is cumbersome, but I don't see how to do it on an easier way.
First, create a function. This function will make use of system view sys.syslanguages to get the correct name of month in spanish. Parameters are a valid date and language (alias on sys.syslanguage view).
CREATE FUNCTION [dbo].[fn_GetMonthName] (
#Date DATETIME,
#Language NVARCHAR(100)
)
RETURNS NVARCHAR(400)
AS
BEGIN
DECLARE #i INT, #m INT,#mlist NVARCHAR(1000)
SET #m = MONTH(#Date)
SET #mlist = (SELECT months FROM sys.syslanguages WHERE ALIAS = #language)
SET #i = 1
WHILE(#i < #m)
BEGIN
SET #mlist = REPLACE(#mlist, SUBSTRING(#mlist,1,CHARINDEX(',',#mlist)) ,'')
SET #i = #i + 1
END
SET #mlist = (CASE CHARINDEX(',',#mlist) WHEN 0 THEN #mlist ELSE SUBSTRING(#mlist,0,CHARINDEX(',',#mlist) ) END )
RETURN #mlist
END
GO
Then call the function anywhere you need to:
SELECT CONVERT(VARCHAR(20), GETDATE(), 100) AS CurrentDate,
dbo.fn_GetMonthName (GETDATE(), 'Spanish') AS [Mes-Month]
Result:
CurrentDate Mes-Month
May 24 2013 12:02AM Mayo
Taken from Get Language specific Month Name from SQL
Take a look at: http://www.sqlservercurry.com/2010/11/change-default-language-for-sql-server.html
You can temporarily set the language to spanish, not sure how feasible this is for you. The other way to do it would be to write your own months function, and maybe pass it a 2nd parameter that then decides what the output would be.
This function will translate the month within a string it's based on the sys.syslanguages table.
i.e. SELECT dbo.fn_tranMonth(2,0,'1 déc. 2014 10:26:14 UTC+00:00')
Results:
1 Dec. 2014 10:26:14 UTC+00:00
CREATE FUNCTION [dbo].[Split] (#sep char(1), #s varchar(8000))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(#sep, #s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(#sep, #s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT
SUBSTRING(#s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
CREATE FUNCTION dbo.fn_tranMonth
(
#fromLan INT
,#toLan INT
,#string VARCHAR(MAX)
)
RETURNS
VARCHAR(50)
AS
BEGIN
DECLARE #TTTT AS TABLE(PK INT IDENTITY(1,1)
,fromMonth VARCHAR(50)
,toMonth VARCHAR(50)
)
DECLARE
#fromMonths VARCHAR(200)
,#toMonths VARCHAR(200)
,#fromMonth VARCHAR(20)
,#toMonth VARCHAR(20)
,#rowNum INT=12;
SELECT #fromMonths=shortmonths
FROM SYS.syslanguages
WHERE langid=#fromLan;
SELECT #toMonths=shortmonths
FROM sys.syslanguages
WHERE langid=#toLan;
INSERT #TTTT(fromMonth)
SELECT S
FROM dbo.Split(',',#fromMonths);
DECLARE #TTTT2 AS TABLE(PK INT IDENTITY(1,1)
,toMonth VARCHAR(50)
)
INSERT #TTTT2(toMonth)
SELECT S
FROM dbo.Split(',',#toMonths);
UPDATE #TTTT
SET toMonth=B.toMonth
FROM
#TTTT A
JOIN #TTTT2 B ON A.PK=B.PK;
DECLARE
#loopPos INT=0
,#returnMonth VARCHAR(50);
WHILE #loopPos<#rowNum
BEGIN
SET #loopPos+=1;
SELECT
#fromMonth=fromMonth
,#toMonth=toMonth
FROM #TTTT
WHERE PK=#loopPos;
SET #string=REPLACE(#string,#fromMonth,#toMonth);
END;
RETURN #string;
END
try this:
SELECT CONVERT(VARCHAR(10),GETDATE(), 103)
or
this code, return a VARCHAR(10) with date EN ESPAÑOL, leches.
IDEA (separator used: '-'):
Get format YYYY-MM-DD NVARCHAR(10).
Get format DD-MM-YYYY nvarchar(10)
Use the function
sample:
select dbo.date2txt(GETDATE ())
function to create:
create function [dbo].[AFecha] (
#fecha NVARCHAR(10)
)
returns NVARCHAR(10)
as
begin
Declare #r nvarchar(10)
if substring(#Fecha,3,1) = '-'
set #r = #Fecha
else
set #r = substring(#fecha,9,2)+'-'+substring(#fecha,6,2)+'-'+left(#fecha,4)
Return #r
End
go
create FUNCTION [dbo].[NTSDate](#fecha DateTime)
RETURNS nVarChar(10) AS
BEGIN
DECLARE #salida nVarChar(10)
set #salida = STR(year(#fecha),4,0) + '-' + RIGHT('0' + LTRIM(month(#fecha)),2) + '-' + RIGHT('0' + LTRIM(day(#fecha)),2)
return (#salida)
End
go
ALTER function [dbo].[Date2Txt](#Fecha as datetime) returns nvarchar(10)
as
begin
return dbo.afecha(dbo.NTSDate(#Fecha))
end
go
You can do the following:
FORMAT(GETDATE(), 'MMMM d,yyyy','es-US')
The last parameter for format datetime is an optional culture parameter that does exactly what you need when passed the right culture.
If you needed to localize to a different language you could find the string to do so from the link below.
https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-input-locales-for-windows-language-packs?view=windows-11

Get specific Count for Character from a column without using a function or Stored Proc

I have a column on a table [SampleTable] called [MyColumn] and i would like the number of time this character appears on the column. The character is ;
Excel has a simple solution for this
=LEN()-LEN(SUBSTITUTE(,";",""))
SELECT LEN(MyColumn) - LEN(REPLACE(MyColumn, ';', ''))
FROM SampleTable
WHERE ...
For best readability in code this is best done with a UDF. For example, the one from here:
CREATE FUNCTION [dbo].[ufn_CountChar] ( #pInput VARCHAR(1000), #pSearchChar CHAR(1) )
RETURNS INT
BEGIN
DECLARE #vInputLength INT
DECLARE #vIndex INT
DECLARE #vCount INT
SET #vCount = 0
SET #vIndex = 1
SET #vInputLength = LEN(#pInput)
WHILE #vIndex <= #vInputLength
BEGIN
IF SUBSTRING(#pInput, #vIndex, 1) = #pSearchChar
SET #vCount = #vCount + 1
SET #vIndex = #vIndex + 1
END
RETURN #vCount
END
GO