Issue creating function with a "with" - sql-server

I am trying to create this function(variable names changed so allow naming mistakes as when tested original without function works fine),
CREATE FUNCTION [dbo].[GetQuality](#FruitID VARCHAR(200))
RETURNS varchar(200)
AS
BEGIN
DECLARE #Result varchar(200)
SET #Result = (
WITH
latest AS
(
SELECT * FROM (SELECT TOP 1 * FROM Fruits_Crate WHERE FruitID like #FruitID ORDER BY ExpiryDate DESC) a
),
result AS
(
SELECT
latest.ExpiryDate as LatestExpiryDate, latest.Size as LatestSize, latest.Weight as LatestWeight,
previous.ExpiryDate as PreviousExpiryDate, previous.Size as PreviousSize, previous.Weight as PreviousWeight,
CASE SIGN((latest.Weight * latest.Size) - (previous.Weight * previous.Size))
WHEN 1 THEN 'Increased'
WHEN 0 THEN 'Static'
WHEN -1 THEN 'Decreased'
ELSE 'No Previous Data'
END AS Movement
FROM (SELECT TOP 1 * FROM (SELECT TOP 2 * FROM Fruits_Crate WHERE FruitID like #FruitID ORDER BY ExpiryDate DESC) x ORDER BY ExpiryDate) previous
FULL OUTER JOIN latest ON previous.FruitID = latest.FruitID
)
SELECT result.Movement AS FruitMovement from result;
)
RETURN #Result
END
Error
Msg 156, Level 15, State 1, Procedure GetQuality, Line 10
Incorrect syntax near the keyword 'WITH'.
Msg 319, Level 15, State 1, Procedure GetQuality, Line 10
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Procedure GetQuality, Line 14
Incorrect syntax near ','. Msg 102, Level 15, State 1, Procedure GetQuality, Line 31 Incorrect syntax near ')'.

I think you can move the assignment down, and put a semi colon before the with, and all should be good.
CREATE FUNCTION [dbo].[GetQuality](#FruitID VARCHAR(200))
RETURNS varchar(200)
AS
BEGIN
DECLARE #Result varchar(200);
WITH
latest AS
(
SELECT * FROM (SELECT TOP 1 * FROM Fruits_Crate WHERE FruitID like #FruitID ORDER BY ExpiryDate DESC) a
),
result AS
(
SELECT
latest.ExpiryDate as LatestExpiryDate, latest.Size as LatestSize, latest.Weight as LatestWeight,
previous.ExpiryDate as PreviousExpiryDate, previous.Size as PreviousSize, previous.Weight as PreviousWeight,
CASE SIGN((latest.Weight * latest.Size) - (previous.Weight * previous.Size))
WHEN 1 THEN 'Increased'
WHEN 0 THEN 'Static'
WHEN -1 THEN 'Decreased'
ELSE 'No Previous Data'
END AS Movement
FROM (SELECT TOP 1 * FROM (SELECT TOP 2 * FROM Fruits_Crate WHERE FruitID like #FruitID ORDER BY ExpiryDate DESC) x ORDER BY ExpiryDate) previous
FULL OUTER JOIN latest ON previous.FruitID = latest.FruitID
)
SELECT #RESULT = result.Movement AS FruitMovement from result;
RETURN #Result
END

Related

How to delete 1000 rows at a time with SQL Server OPENQUERY

I need to delete rows in a link server's table, 1000 rows at a time.
My code is the following:
WHILE (SELECT COUNT(*) FROM OPENQUERY (SqlServerAcc, 'SELECT * FROM titles ') > 1000)
BEGIN
DELETE OPENQUERY (SqlServerAcc,
'SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY Id) AS RowNumber FROM tbl) t WHERE RowNumber <= 1000');
END
But I do have errors:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '>'.
at the expression > 1000.
I don't understand why this does not work.
Bonus: how can we make the name of the server not hard-coded; in PRD, it should be SqlServerPrd, but it seems that OPENQUERY does not accept variables for its arguments...

Why SQL Server doesn't see database

I'm implementing full-text search on SQL Server 2014. I've added dbo.Blocks table like dbo.Articles in the 4th step in this tutorial http://www.mikesdotnetting.com/article/298/implementing-sql-server-full-text-search-in-an-asp-net-mvc-web-application-with-entity-framework
And I have simplified Search procedure for my purposes:
CREATE PROCEDURE Search
#SearchTerm varchar(8000),
#CurrentPage int = 1,
#PageSize int = 20
AS
BEGIN
DECLARE #NearPredicate varchar(8000),
#AndPredicate varchar(8000),
#TotalRecords int
SELECT
#NearPredicate = COALESCE(#NearPredicate + ' NEAR ', '') + items
FROM
dbo.Split(#SearchTerm, ' ')
LEFT JOIN
sys.fulltext_system_stopwords ON items = stopword
WHERE
stopword IS NULL
SET #AndPredicate = REPLACE(#NearPredicate, 'NEAR', 'AND')
SET #NearPredicate = '(' + #NearPredicate + ')'
SET #TotalRecords = (
SELECT
COUNT(*)
FROM
AbstractBuildBlocks
WHERE CONTAINS(*, #AndPredicate )
)
SELECT a.SiteId,
a.Content,
ct.Rank,
#TotalRecords AS TotalRecords
FROM
AbstractBuildBlocks a
INNER JOIN CONTAINSTABLE (Blocks, *, #NearPredicate ) AS ct ON a.Id = ct.[Key]
ORDER BY
ct.RANK DESC
OFFSET (#CurrentPage - 1) * #PageSize ROWS FETCH NEXT #PageSize ROWS only
END
I try to test this in SQL Server Management Studio: press new query, print EXEC Search #SearchTerm="sample", #CurrentPage = 1 and hit !Execute.
There are two problems:
Small: SQL Server Management Studio underlines Search in my query and says:
Couldn't find stored procedure 'Search'
Big: server when executing query throws an error:
Msg 208, Level 16, State 1, Procedure Search, Line 34
Invalid object name 'Blocks'.
on line 34:
FROM dbo.Split(#SearchTerm, ' ') /*line 34*/
I found it strange because I've created database dbo.Blocks and in Split Function I even don't use this table.
Don't know if it important but dbo.Split is underlined with red, message: Invalid object name, but despite this procedure has been successfully created and stored.
And the last I've just try to replace Blocks with dbo.Blocks
here:
FROM
AbstractBuildBlocks a
INNER JOIN CONTAINSTABLE (Blocks, *, #NearPredicate ) AS ct ON a.Id = ct.[Key]
and recompile procedure - the error now:
Msg 208, Level 16, State 1, Procedure Search, Line 34
Invalid object name 'dbo.Blocks'. /instead of blocks/
UPDATE I've used this
SELECT '['+SCHEMA_NAME(schema_id)+'].['+name+']'
AS SchemaTable
FROM sys.tables
There is no Blocks table in result. And this is Blocks's properties
You're trying to use the Blocks object as a table but it's the name of your full text catalog. If you look at the CONTAINSTABLE documentation, the first parameter is a table that has been full text indexed. Should that first parameter be dbo.Search?

SQL scalar valued function throwing "Invalid Object Name" error

My SQL scalar valued function is defined in the following code:
CREATE FUNCTION CtrAmount ( #Ctr_Id int )
RETURNS MONEY
AS
BEGIN
DECLARE #CtrPrice MONEY
SELECT #CtrPrice = SUM(amount)
FROM Contracts
WHERE contract_id = #Ctr_Id
RETURN(#CtrPrice)
END
GO
SELECT * FROM CtrAmount(345)
GO
But when it comes to the SELECT line, I am getting this error:
Msg 208, Level 16, State 3, Line 14
Invalid object name 'CtrAmount'.
Int(10) - unknown type
CREATE FUNCTION dbo.CtrAmount
(
#Ctr_Id INT
)
RETURNS MONEY
AS
BEGIN
RETURN (
SELECT SUM(amount)
FROM dbo.Contracts
WHERE contract_id = #Ctr_Id
)
END
GO
SELECT dbo.CtrAmount(345)
GO

Is it possible to have a view in sql-server 2008 that splits one row into many?

The back story is I am trying to write a view that takes a table who's every row is an ID and serialized data for that ID in a clob and presents it in sql navigable form. basically my code looks like:
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM
SOURCE_TABLE,
FUNCTION_WHICH_UNSERIALIZES((SELECT DATA FROM SOURCE_TABLE WHERE ID = SOURCE_ID)
I tried putting the function in the select statement, but that just gave a syntax error about it being undefined. When it runs the error is usually about a subquery returning too many values. I could just unserialize the data in batches, but now I'm really curious what's going wrong.
Example Data
#0History:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567SourceMode:6:ANNUAL.ModeChanges:UniqueIndex:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567OldValue:1:+NewValue:6:ANNUALChangeType:1:AChangeDate:20:6/03/2013 2:49:32 AM.
#0History:UniqueIndex:95:NOTTHESAME0987654|ALPHANUMERIC534|PRETEND349235|95CHARACTERSID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236SourceMode:26:ANNUAL|C-P-D|ANNUAL|ANNUALLoan:3:|||ModeChanges:UniqueIndex:95:00487SOMETHING4264500ORD|992581PROBABLY04ORD|0048SHOULD238BET|0095CHARS436PR638FGP07VDCID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236OldValue:7:+|+|+|+NewValue:26:ANNUAL|C-P-D|ANNUAL|ANNUALChangeType:7:A|A|A|AChangeDate:91:12/22/2013 11:53:11 PM|4/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM.
The data is serialized table data of the form COLUMN_NAME:LENGTH_OF_ENTRY:DATA_FOR_COLUMN_ROW_1|DATA_FOR_COLUMN_ROW2|....NEXT_COLUMN_NAME...
Example of Function:
CREATE FUNCTION FUNCTION_THAT_UNSERIALIZES (#clob varchar(max),#colname varchar(max)) RETURNS #NewValue TABLE (ID INT,value varchar(max)) AS
BEGIN
DECLARE #colstart INT,#lenstart INT,#lenend INT,#collen VARCHAR(MAX),#lngth INT,#tmp VARCHAR(MAX), #rowid INT,#value VARCHAR(max),#next INT;
SELECT
#colstart = CHARINDEX(#colname,#tmp)+1,
#lenstart = CHARINDEX(':',#tmp,#colstart)+1,
#lenend = CHARINDEX(':',#tmp,#lenstart),
#collen = SUBSTRING(#tmp,#lenstart,#lenend - #lenstart),
#lngth = CAST (#collen AS INT),
#tmp = SUBSTRING(#tmp,#lenend,#lngth);
WHILE LEN(#tmp) > 0 BEGIN
SET #next = CHARINDEX('|',#tmp);
IF #next > 0 BEGIN
SET #value = SUBSTRING(#tmp,0,#next);
SET #tmp = SUBSTRING(#tmp,#next+1,LEN(#tmp) - #next);
END ELSE BEGIN
SET #value = #tmp;
SET #tmp = '';
END
INSERT INTO #NewValue VALUES(#rowid,#value)
SET #rowid = #rowid+1;
END
RETURN
Example Error
Msg 512, Level 16, State 1, Line 7
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Msg 4104, Level 16, State 1, Line 15
The multi-part identifier "SOURCE_TABLE.SOURCE_ID" could not be bound.
.. I think there might have been another one, but can't figure out how to reproduce it right this minute.
I think this might be the syntax you need to accomplish what I think you are trying to do.
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM SOURCE_TABLE
CROSS APPLY FUNCTION_WHICH_UNSERIALIZES(DATA, #colname) a
I'm not certain what your #colname parameter should be; it is left out of your code in the question.

SQL server can not accept median function

I wrote this Median function but it is executing with errors.. Can someone guide me what's wrong in the code?
BEGIN
CREATE TABLE #ITEMORDERDETAILS
(
ITEM CHAR(15),
QTYSHP DECIMAL(21, 6),
RQDATE DATETIME
)
DECLARE #Median FLOAT
DECLARE #ITEM CHAR(15)
DECLARE #ORDERCNT INT
SET #ITEM=#ITEMN
INSERT #ITEMORDERDETAILS
SELECT ITEM,
QTYSHP,
RQDATE
FROM tbl123456
WHERE PRICE != '0'
AND SALESMN != 'WB'
AND RQDATE > ( getdate () - 180 )
AND ITEM = #ITEM
UNION
SELECT ITEM,
QTYSHP,
RQDATE
FROM tbl123
WHERE PRICE != '0'
AND SALESMN != 'WB'
AND RQDATE > ( getdate () - 180 )
AND ITEM = #ITEM
SELECT #ORDERCNT = count (1)
FROM #ITEMORDERDETAILS
--SELECT #ORDERCNT
SELECT #Median = ( sum(QTYSHP) / #ORDERCNT )
FROM #ITEMORDERDETAILS
SELECT #Median AS 'Median'
--SELECT * from #ITEMORDERDETAILS
DROP TABLE #ITEMORDERDETAILS
RETURN #Median
END
ERRORS
Msg 2772, Level 16, State 1, Procedure
f_Get_Average_Order_Size_Median, Line 34 Cannot access temporary
tables from within a function.
Msg 2772, Level 16, State 1, Procedure
f_Get_Average_Order_Size_Median, Line 35 Cannot access temporary
tables from within a function.
Msg 2772, Level 16, State 1, Procedure
f_Get_Average_Order_Size_Median, Line 42 Cannot access temporary
tables from within a function.
Msg 156, Level 15, State 1, Procedure
f_Get_Average_Order_Size_Median, Line 46 Incorrect syntax near the
keyword 'SELECT'.
The reason is in your error message:
Line 34 Cannot access temporary tables from within a function
If you make a function, there are limits to what you can access.
However, if you use SQL Server 2012, you do not need to write your own median function but you can use PERCENTILE_DISC
PERCENTILE_DISC (0.5) WITHIN GROUP (ORDER BY XXXX)
OVER (PARTITION BY YYYY) AS Median

Resources