How to incement row id with identity to off - sql

I am getting this error while i do select.
DECLARE #TopID INT
SELECT #TopID = MAX([QuestionId]) from [SurveyQuestions];
SELECT
#TopID = #TopID + 1
,[questiontext]
,[DeptID]
,[SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions] where surveyid =80
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations.
I know there is a posibility to fix this error with identity set to ON.but i dont want that as my db is hosted in legecy application, changing this will make other things to break.

This has nothing to do with the identity. It has to do with the select. You have:
SELECT #TopID = #TopID + 1,
[questiontext], [DeptID], [SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions]
WHERE surveyid = 80
This has an assignment and it returns values. I think you really want:
SELECT #TopId + (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) as rownum,
[questiontext], [DeptID], [SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions]
WHERE surveyid = 80;
Note: If you actually want the results in a particular order, then add an ORDER BY both to the query and to the ROW_NUMBER().

It is the way you are selecting, you cant use operators in select with other columns being fetched. See this link for some explanation on what you are doing wrong.
I think what you really require is this :
DECLARE #TopID INT
SELECT #TopID = MAX([QuestionId]) from [SurveyQuestions];
SELECT
#TopID + 1
,[questiontext]
,[DeptID]
,[SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions] where surveyid =80
EDIT :
Or a ROW_NUMBER based solution like :
DECLARE #TopID INT
SELECT #TopID = MAX([QuestionId]) from [SurveyQuestions];
SELECT
#TopID + ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as TopID
,[questiontext]
,[DeptID]
,[SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions] where surveyid =80
Improving a bit on the Previous Answer (combined into one query):
SELECT (
SELECT TOP 1 QuestionId
FROM SurveyQuestions
ORDER BY QuestionId DESC
)
+ ROW_NUMBER() OVER ( ORDER BY (SELECT 1)) AS TopID
, [questiontext], [DeptID], [SurveyID]
FROM [SOSS].[dbo].[SurveyQuestions]
WHERE surveyid = 80
SQL Fiddler
Another Alternative, combing your 2 queries :
SELECT
(SELECT MAX(ID) FROM ForgeRock) as MAx_Id
, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as Row_ID,
(SELECT TOP 1 ID FROM ForgeRock ORDER BY Id DESC) +
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as New_Id,
productName,
description
FROM
ForgeRock
SQL Fiddler

Related

The multi-part identifier "company.ID" could not be bound

This query breaks because I have a multipart identifier that could not be bound. I have searched around and have tried a few suggestions online and none of which work for me. I have made sure that there is no typing errors.
WITH TempResult AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY RequestDate) as RowNum,
[BillSearchesId],
[RequestDate],
company.[ID] AS [CompanyId],
users.ID AS [UserID],
[DeedsOffice],
[Description],
[DocNo],
[MicrofilmRefNumber],
[UserReference],
[USERNAME],
[TextCopyRequest],
[NotFound],
STUFF ((SELECT ', ' + CAST([FormatId] AS VARCHAR(20))
FROM [dbo].[DeedsDocumentCopyLocations] ddcl
WHERE ddcl.DocumentCopyId = ddcr.DocumentCopyId
FOR XML PATH('')), 1, 1, '') AS [FormatsAvailable]
FROM
[dbo].[DocumentCopyRequestsTable] ddcr
INNER JOIN
[dbo].[DocumentCopiesTable] ddc ON ddc.id = ddcr.DocumentCopyId
INNER JOIN
[dbo].[USERSTable] users ON users.ID = ddcr.UserId
INNER JOIN
[dbo].[COMPANYTable] company ON company.ID = ddcr.CompanyId
)
SELECT TOP (#LastRec-1) *
FROM TempResult
WHERE RowNum > #FirstRec
AND company.ID = #companyID // The multi-part identifier "company.ID" could not be bound.
AND RowNum < #LastRec
AND DocNo LIKE ISNULL(#DocumentNumber + '%',DocNo)
AND [Description] LIKE ISNULL(#Description + '%',[Description])
AND UserReference LIKE ISNULL(#Reference + '%', UserReference)
There's no table or table alias Company in that SELECT after your CTE - you cannot reference a table that isn't part of your SELECT ....
But that company.ID is available from the CTE already - just use that!
WITH TempResult AS
(
SELECT
....
company.[ID] AS [CompanyId], -- this defines a column "CompanyId" in your CTE
....
FROM
....
)
SELECT TOP (#LastRec-1) *
FROM TempResult
WHERE RowNum > #FirstRec
-- use the "CompanyID" column from your "TempResult" CTE .....
AND CompanyId = #companyID
......

How to add counting number to a record in sql

I want to add a number to specific column in my data:but my #id is static and doesn't change, what do I miss
//that's what I need
names
-----
david1
david2
david3
//that's my code
DECLARE #var INT
SET #var = 0
update [dbo].[ContactBase]
set FirstName = 'david + convert(varchar(10),#var )
set #var =#var + 1;
Have a look at the following.
;
WITH CTE
AS (SELECT FirstName
, ROW_NUMBER() OVER (ORDER BY (SELECT 1
)) RN
FROM ContactBase
)
SELECT *
FROM CTE
;
WITH CTE
AS (SELECT FirstName
, ROW_NUMBER() OVER (ORDER BY (SELECT 1
)) RN
FROM ContactBase
)
UPDATE CTE
SET FirstName = FirstName + CAST(RN AS VARCHAR(10))
The first call just shows you the output from the cte, the second one actually handles updating.
Also using the row number option you can also seperate out by names to give you david1,david2,Jon1,Jon2,etc quite simply. Is a handy way of de-duping data.
DECLARE #ContactBase AS TABLE (FirstName VARCHAR(10))
INSERT INTO #ContactBase
(FirstName)
VALUES ('David'),('David'),('David')
SELECT * FROM #ContactBase
;WITH CTE
AS (SELECT FirstName
, ROW_NUMBER() OVER (ORDER BY (SELECT 1
)) RN
FROM #ContactBase
)
UPDATE CTE
SET FirstName = FirstName + CAST(RN AS VARCHAR(10))
SELECT * FROM #ContactBase
I don't understand what you want... You want to
Add a number (id) at the end of FirstName ?
Do a loop who add element in you database with new id ?
Use ROW_NUMBER to generate the numbers.
update n
set firstname = 'david' + cast(num as varchar(10))
from
(select firstname, row_number() over (order by firstname) as num from dbo.contactbase) n;
REXTESTER demo: http://rextester.com/CZDJ47320

SQL split and merge string

this is my problem:
I got a string from a column like this:
**0756FJ89045GJD38**.pdf
Now i have to generate a path by this string:
/home/ars/07/56/FJ/89/04/5G/JD/38/0756FJ89045GJD38.pdf
I have to take two characters and build it up to one path level from left to right.
Maybe u can help me, thanks!
This may help:
DECLARE #p nvarchar(100) = '**0756FJ89045GJD38**.pdf',
#n int = 3
;WITH cte AS (
SELECT STUFF(REPLACE(SUBSTRING(#p,1,CHARINDEX('.',#p)-1),'*',''),1,0,'/') as p, 1 [level]
UNION ALL
SELECT STUFF(p,[level]+#n,0,'/'), [level]+#n
FROM CTE
WHERE LEN(STUFF(p,[level]+#n,0,'/')) >= [level]+#n
)
SELECT TOP 1 #p = '/home/ars'+p +'/'+REPLACE(#p,'*','')
FROM cte
ORDER BY [level] DESC
SELECT #p
Output:
/home/ars/07/56/FJ/89/04/5G/JD/38/0756FJ89045GJD38.pdf
EDIT:
If there is a table with PDF file names and all names are equal size, than you can do this way:
DECLARE #n int = 3
;WITH pdf AS (
SELECT *
FROM (VALUES
('**0756FJ89045GJD38**.pdf'),
('**1729DA8CD189700A**.pdf'),
('**A6710936BCD47832**.pdf'),
('**00A764D617B93978**.pdf')
) as t(file_)
)
,cte AS (
SELECT file_, STUFF(REPLACE(SUBSTRING(file_,1,CHARINDEX('.',file_)-1),'*',''),1,0,'/') as p, 1 [level]
FROM pdf
UNION ALL
SELECT file_, STUFF(p,[level]+#n,0,'/'), [level]+#n
FROM CTE
WHERE LEN(STUFF(p,[level]+#n,0,'/')) >= [level]+#n
)
SELECT TOP 1 WITH TIES '/home/ars'+p +'/' + REPLACE(c.file_,'**','')
FROM cte c
ORDER BY ROW_NUMBER() OVER (PARTITION BY file_ ORDER BY [level]) DESC
Output:
/home/ars/00/A7/64/D6/17/B9/39/78/00A764D617B93978.pdf
/home/ars/A6/71/09/36/BC/D4/78/32/A6710936BCD47832.pdf
/home/ars/17/29/DA/8C/D1/89/70/0A/1729DA8CD189700A.pdf
/home/ars/07/56/FJ/89/04/5G/JD/38/0756FJ89045GJD38.pdf

SQL replace from list

I'm trying to figure our how I can replace a string using data from another table
I have a table that looks like this:
Id Translation
1 Peter
2 Sandra
3 Olga
Now I want to select all and replace the translations using a list that looks like this:
Original New
e #
r ?
lg *%
So that the select list looks like this:
Id Translation
1 P#t#?
2 Sand?a
3 O*%a
So, for each translation, I need to have a REPLACE(Translation,Original,New).
Or in other words: I need to go through every "Translation" in my first list and make another loop in my replacement table to see what to replace
Bare in mind that the first list has 25'000 rows and the second has 50'000, so I can't just type it by hand :)
EDIT
Just to clarify:
The Original and New from my look up table can be both letters and words so the table can looks like this:
Original New
one two
three fifty
sun moon
To do this in one query, you need to use a recursive CTE. Something like:
with trans as (
select t.original, t.new, row_number() over (order by t.original) as seqnum,
count(*) over () as cnt
from translations
),
t as (
select tt.id, tt.string, replace(tt.string, trans.original, trans.new) as replaced,
seqnum + 1 as seqnum, cnt
from totranslate tt join
trans
on trans.id = 1
union all
select t.id, t.string, replace(t.string, trans.original, trans.new),
seqnum + 1 as seqnum, cnt
from t join
trans
on t.seqnum = trans.id
where t.seqnum <= t.cnt
)
select t.id, t.string, t.replaced
from t
where seqnum = cnt;
You can use a UDF:
CREATE FUNCTION [dbo].[Translate]
(
-- Add the parameters for the function here
#Str nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #Result nvarchar(max) = #Str;
SELECT #Result = replace(#Result,Original,New) from dbo.Mappings order BY Pos;
RETURN #Result;
END
Here I assumed the table containing translations is called dbo.Mappings and beside the Original and New columns you need another column Pos int which will be used to determine the order in which the translations are applied (to address the problems mentioned by #Thorsten Kettner in comments)
Also with recursive cte:
DECLARE #translations TABLE
(
Id INT ,
Translation NVARCHAR(20)
)
INSERT INTO #translations
VALUES ( 1, 'Peter' ),
( 2, 'Sandra' ),
( 3, 'Olga' )
DECLARE #replacements TABLE
(
Original VARCHAR(2) ,
New VARCHAR(2)
)
INSERT INTO #replacements
VALUES ( 'e', '#' ),
( 'r', '?' ),
( 'lg', '*%' );
WITH cte1 AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY (SELECT 1)) rn
FROM #translations CROSS JOIN #replacements),
cte2 AS (SELECT Id, rn, REPLACE(Translation, Original, New) AS NTranslation
FROM cte1
WHERE rn = 1
UNION ALL
SELECT c2.Id, c2.rn + 1, REPLACE(c2.NTranslation, c1.Original, c1.New)
FROM cte1 c1
JOIN cte2 c2 ON c2.Id = c1.Id AND c2.rn + 1 = c1.rn)
SELECT * FROM cte2
WHERE rn = (SELECT COUNT(*) FROM #replacements)
ORDER BY Id
EDIT:
WITH cte1 AS (SELECT t.*, p.Id AS Old, p.Code, ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY (SELECT 1)) rn
FROM translations t CROSS JOIN Property p),
cte2 AS (SELECT Id, rn, REPLACE(Trans, Old, Code) AS NTranslation
FROM cte1
WHERE rn = 1
UNION ALL
SELECT c2.Id, c2.rn + 1, REPLACE(c2.NTranslation, c1.Old, c1.Code)
FROM cte1 c1
JOIN cte2 c2 ON c2.Id = c1.Id AND c2.rn + 1 = c1.rn)
SELECT * FROM cte2
WHERE rn = (SELECT COUNT(*) FROM Property)
ORDER BY Id
Here is something I worked out that will allow you to replace multiple characters with one specified string.
[Split2] is stolen from https://blogs.msdn.microsoft.com/amitjet/2009/12/11/convert-comma-separated-string-to-table-4-different-approaches/
USE <Your Database>
GO
CREATE FUNCTION [dbo].[Split2]
(
#strString varchar(4000)
)
RETURNS #Result TABLE
(
RID INT IDENTITY(0,1) Primary Key
,Value varchar(4000)
)
AS
BEGIN
WITH StrCTE(start, stop) AS
(
SELECT 1, CHARINDEX(',' , #strString )
UNION ALL
SELECT stop + 1, CHARINDEX(',' ,#strString , stop + 1)
FROM StrCTE
WHERE stop > 0
)
INSERT INTO #Result
SELECT SUBSTRING(#strString , start, CASE WHEN stop > 0 THEN stop - start ELSE 4000 END) AS stringValue
FROM StrCTE
RETURN
END
GO
USE <Your Database>
GO
CREATE FUNCTION [dbo].[MultiReplace]
(
#MyString varchar(MAX)
,#RepChars varchar(4000)
,#NewChars varchar(4000)
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE #CurRow int = 0
DECLARE #MaxRow int
SELECT #MaxRow = MAX(RID)
FROM dbo.split2 ( #RepChars )
WHILE #CurRow <= #MaxRow
BEGIN
SELECT #MyString = REPLACE(#MyString,VALUE,#NewChars)
FROM dbo.split2 ( #RepChars )
WHERE RID = #CurRow
SET #CurRow = #CurRow + 1
END
RETURN (#MyString);
END
GO
In this example I replace each character with no space
SELECT [dbo].[MultiReplace]('6th month 2016-06 (test / requested)',',1st,2nd,3rd,4th,5th,6th,0,1,2,3,4,5,6,7,8,9,(,),/,-,+, ','')
Result:
monthtestrequested
I hope this is useful for you.

initialize and increment variable inside cte query sqlserver 2008

I am using sqlserver 2008 ,I want to initialize and increment variable (#NUMTwo) both at the same time, in my second part(Problem Line).
I am creating a cte query.
Is this possible , if yes then please let me know.
following is a sample example.I hope i am clear.
CREATE table #TempTable
(
childProductID INT,parentProductID INT,productModel varchar(50),[Num2] VARCHAR(100)
)
DECLARE #NUMTwo INT = 0
WITH tableR AS
(
-- First Part
SELECT childProductID = null,parentProductID=null,productModel from Products where productid in (#a),[Num2] = convert(varchar(100), '')
UNION ALL
--Second Part
SELECT e.childProductID,e.parentProductID,prd.productModel FROM ProductIncludes AS e
,[Num2] = convert(varchar(100),'1.' + #NUMTwo+=1 ) -- Problem line
INNER JOIN Products AS PRD ON e.childProductID = PRD.productID
WHERE parentProductID in (#a)
)
INSERT INTO #TempTable(childProductID,parentProductID,productModel,[Num2])
SELECT childProductID,parentProductID,productModel,[Num2]
END
SELECT * FROM #TempTable
You need to "Initialize" a column in the acnhor part of the query, and then "oncrement" this column in the recursive parts.
Something like
DECLARE #NUMTwo INT = 0
;WITH Test AS (
SELECT [Num2] = convert(varchar(MAX), ''),
#NUMTwo [N]
UNION ALL
SELECT [Num2] = '1.' + convert(varchar(MAX),[N]+1),
[N]+1
FROM TEst
WHERE [N] < 10
)
SELECT *
FROM Test
SQL Fiddle DEMO
If the parameter #NUMTwo is just for numbering rows you can use the ROW_NUMBER() OVER(...) instead of it like so:
WITH tableR AS
(
SELECT childProductID = NULL, parentProductID = NULL,
productModel, NUMTwo = CAST('0' AS VARCHAR(10))
FROM Products
WHERE
productid in (#a),
[Num2] = convert(varchar(100), '')
UNION ALL
SELECT e.childProductID, e.parentProductID,
prd.productModel,
NUMTwo = '1.' +
CAST( ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS VARCHAR(10))
FROM ProductIncludes AS e
INNER JOIN Products AS PRD ON e.childProductID = PRD.productID
WHERE parentProductID in (#a)
)