SQL: Update multiple rows (Top 100) with sequential data - sql

I am working on SQL Server 2008 and trying to update a table. I just need the first one hundred rows to be updated with a 15 digit sequence. I have tried the following:
Declare #id varchar
Set #id = 2435435345962
UPDATE TOP (100) Table1
SET #id = Column_nm = #id + 1
GO
but I am getting the following error message:
Msg 426, Level 16, State 1, Line 3
The length 1 of the receiving variable is less than the length 15 of the column 'Column_nm'.

Several things. You want start in 0 so you can add 00-99.
So lets start with the base
WITH cte as (
SELECT TOP 100 *,
ROW_NUMBER() OVER (ORDER BY somefield) -1 as rn -- row_number start with 1.
FROM Table1
ORDER BY somefield
)
UPDATE cte
SET anotherfield = '1234567890ABC' + REPLACE(STR(rn, 2, 0), ' ', '0')
^^ 13 chars ^^ two digits number

The error message is about length of your variable. In SQL Server the default length of varchar is 1 (from msdn.microsoft.com i have only the french link sorry).
Declare #id varchar(15)
Set #id = 2435435345962
UPDATE top (100) Table1
SET #id = Column_nm = #id + 1
GO
You must declare id with length of 15 to put your string in this variable.

Related

SQL Server: how to update a column with a value that is in that column when another number in another column is >1

I have a table with the following data:
Part Comp level item_nbr
-------------------------------
abc ab 1 1
null cd 2 2
null ef 3 3
cde gh 1 4
null ij 2 5
null kl 3 6
null mn 4 7
I would like to update the nulls to the value in each level 1, so every level that is >1 is updated with the level one value.
Part Comp level
---------------------
abc ab 1
abc cd 2
abc ef 3
cde gh 1
cde ij 2
cde kl 3
cde mn 4
I am at a loss as to how to achieve this on a very large dataset. Any help would be greatly appreciated!
To explain another way,
part level
abc 1
2
3
Then the next row is populated with another part
efg 1
2
2
etc.
Further clarification:
I need the string"abc" to be filled down with the string "abc" while the column fields below are null. The next row has a string of efg and the following column fields below are null, again, those fields should be filled down with the value "efg" and so on.
The level field = 1 will always have a part number, but all the other levels report up to the level 1 part, so should be populated identically. And repeat.
Hope this makes sense.
Use an updatable CTE with window functions:
with toupdate as (
select t.*,
max(part) over (partition by itm_nbr_not_null) as new_part
from (select t.*,
max(case when part is not null then item_nbr end) over (order by item_nbr) as itm_nbr_not_null
from t
) t
)
update toupdate
set part = new_part
where part is null;
You can run the CTE to see what is happening.
well, from your question what I understand is, you need to update the null column's value until you get a not null value. and you want to continue it up to the last row of the table.
for that scenario, I created a stored procedure, where I read the value of every n-th cell if it is null I changing it with the prev. cell's value, when the cell was not null.
Approach:
create a temporary table/ table variable.
add an extra column, which is basically identity, which will help to rank the column.
iterate a loop until the maximum row is reached.
in each iteration, read the cell value for the i-th row
4.1 if it is not null put it in a temporary variable.
4.2 else, replace/update the i-th cell's value with the temporary variable
continue it, until you reached up to the last row of the table/table variable.
look at my following snippets:
create proc DemoPost
as
begin
declare #table table(serial_no int identity(1,1), name varchar(30), text varchar(30), level int)
insert #table
select Name, Text, Level from Demo
declare #max as int = (select max(serial_no) from #table)
--select #max
declare #i as int =0
declare #temp as varchar(30)
declare #text as varchar(30)
while #i < #max
begin
set #i = #i +1
set #temp = (select name from #table where serial_no = #i)
-- if #temp is not null, fetch its value, otherwise, update/replace it with
-- previously gotten not-null cell's value.
if #temp is not null
begin
set #text = (select name from #table where serial_no = #i)
end
else
begin
update #table
set name = #text where serial_no = #i
end
end
select name, text, level from #table
end
You can update it using temporary table according to the given scenario i thought item_nbr is unique in row Hope this will help
SELECT *
INTO #TEMP
FROM URTablehere
DECLARE #PRev VARCHAR(MAX)
WHILE ( SELECT COUNT(*)
FROM URTablehere
) > 0
BEGIN
DECLARE #ID INT
DECLARE #Part VARCHAR(MAX)
DECLARE #Num INT
SELECT TOP ( 1 )
#ID = level ,
#Part = Part ,
#Num = item_nbr
FROM #TEMP
IF ( #ID = 1 )
BEGIN
SELECT #PRev = #Part
END
IF ( #ID > 1
AND #Part IS NULL
)
BEGIN
UPDATE URTablehere
SET Part = #PRev
WHERE item_nbr = #Num
END
DELETE
FROM #TEMP WHERE item_nbr=#Num
END

SQL CSV as Query Results Column

I have the following SQL which queries a single table, single row, and returns the results as a comma separate string e.g.
Forms
1, 10, 4
SQL :
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT #tmp = #tmp + Form_Number + ', '
FROM Facility_EI_Forms_Required
WHERE Facility_ID = 11 AND EI_Year=2012 -- single Facility, single year
SELECT SUBSTRING(#tmp, 1, LEN(#tmp) - 1) AS Forms
The Facility_EI_Forms_Required table has three records for Facility_ID = 11
Facility_ID EI_Year Form_Number
11 2012 1
11 2012 10
11 2012 4
Form_number is a varchar field.
And I have a Facility table with Facility_ID and Facility_Name++.
How do I create a query to query all Facilites for a given year and produce the CSV output field?
I have this so far:
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT TOP 100 A.Facility_ID, A.Facility_Name,
(
SELECT #tmp = #tmp + B.Form_Number + ', '
FROM B
WHERE B.Facility_ID = A.Facility_ID
AND B.EI_Year=2012
)
FROM Facility A, Facility_EI_Forms_Required B
But it gets syntax errors on using #tmp
My guess is this is too complex a task for a query and a stored procedure may be need, but I have little knowledge of SPs. Can this be done with a nested query?
I tried a Scalar Value Function
ALTER FUNCTION [dbo].[sp_func_EI_Form_List]
(
-- Add the parameters for the function here
#p1 int,
#pYr int
)
RETURNS varchar
AS
BEGIN
-- Declare the return variable here
DECLARE #Result varchar
-- Add the T-SQL statements to compute the return value here
DECLARE #tmp varchar(250)
SET #tmp = ''
SELECT #tmp = #tmp + Form_Number + ', '
FROM OIS..Facility_EI_Forms_Required
WHERE Facility_ID = #p1 AND EI_Year = #pYr -- single Facility, single year
SELECT #Result = #tmp -- SUBSTRING(#tmp, 1, LEN(#tmp) - 1)-- #p1
-- Return the result of the function
RETURN #Result
END
The call
select Facility_ID, Facility.Facility_Name,
dbo.sp_func_EI_Form_List(Facility_ID,2012)
from facility where Facility_ID=11
returns
Facility_ID Facility_Name Form_List
11 Hanson Aggregates 1
so it is only returning the first record instead of all three. What am I doing wrong?
Try the following approach, which is an analogy to SO answer Concatenate many rows into a single text string. I hope it is correct, as I cannot try it out without having the schema and some demo data (maybe you can add schema and data to your question):
Select distinct A.Facility_ID, A.Facility_Name,
substring(
(
Select ',' + B.Form_Number AS [text()]
From Facility_EI_Forms_Required B
Where B.Facility_ID = A.Facility_ID
AND B.EI_Year=2012
ORDER BY B.Facility_ID
For XML PATH ('')
), 2, 1000) [Form_List]
From Facility A

Issues with SQL Max function: "Incorrect syntax new the keyword 'SELECT' "

I'm trying to write a stored procedure to return the maximum value of a column + 1 but for some reason it doesn't want to work.
DECLARE #ID int;
SET #ID = SELECT MAX(ID) + 1 FROM tbl;
I can't for the life of me see what is wrong.
It gives me the error of:
incorrect syntax new the keyword 'SELECT'
No need for SET. Select value directly:
DECLARE #ID int;
SELECT #ID = MAX(ID) + 1 FROM tbl;
Use parentheses ( ... ):
DECLARE #ID int;
SET #ID = (SELECT MAX(ID) + 1 FROM tbl);
or SELECT as suggested by Giorgi. SET is the ANSI standard way of assigning values to variables, SELECT is not. Apart from that using SELECT to assign values to variables is fine, it allows even multiple assignments with one SELECT.
But in general your query seems to be a race condition. Use an IDENTITY column if you want to autoincrement a value. Auto increment primary key in SQL Server Management Studio 2012
You need to consider a scenario when there is no value in the table and MAX returns NULL.
DECLARE #ID int;
SELECT #ID = ISNULL(MAX(ID) , 0) + 1 FROM tbl;
Other adding 1 to null will always yield null.
DECLARE #ID int;
SET #ID = (SELECT MAX(ID) + 1 FROM tbl);
parentheses operator ()
for more information
https://msdn.microsoft.com/en-us/library/ms190276.aspx

Use While loop to calculate values from Table?

I have a following Table Where I need to loop through the records and add values to a variable
Declare #Variable1 INT
SET #Variable1=0
Declare #totalval INT
SET #totalval=0
While (#Variable1<=20)
BEGIN
SET #totalval=#totalval+(Select Salary from EmpTable Where EmpID=9)
PRINT #totalval
SET #Variable1= Variable1+1
END
GO
I cant print the value...I am using SQL server 2005
Thank you all
You could use this instead:
;WITH a AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) num
, *
FROM EmpTable
WHERE EmpID = 9
)
SELECT #totalval = SUM(Salary)
, #Variable1 = COUNT(*)
FROM a
WHERE num <= 20
This would be one of usual ways of doing such task and it's more efficient than looping. ROW_NUMBER() OVER (ORDER BY (SELECT 0)) gives ordinal numbers to records but doesn't change sort.
This is also working (for your requirement):
Fiddle demo here
declare #total int, #records int = 20
select top( #records) #total=isnull(#total,0) + salary
from EmpTable
where empid = 9
-- order by salary (you may need to order by something)
The problem is this line:
SET #Variable1= Variable1+1
that doesn't work, change it to this:
SET #Variable1= #Variable1+1
if you were to leave it you should be getting this error:
Msg 207, Level 16, State 1, Line 11
Invalid column name 'Variable1'.

Auto increment values with alpha numeric

I am trying automatically increment the alpha numeric field (say for productid in product table).
But I am getting an error (see below).
Could somebody please look into this error or any other approach to achieve this task?
My table details:
create table tblProduct
(
id varchar(15)
)
create procedure spInsertInProduct
AS
Begin
DECLARE #PId VARCHAR(15)
DECLARE #NId INT
DECLARE #COUNTER INT
SET #PId = 'PRD00'
SET #COUNTER = 0
--This give u max numeric id from the alphanumeric id
SELECT #NId = cast(substring(id, 3, len(id)) as int) FROM tblProduct group by left(id, 2) order by id
--here u increse the vlaue to numeric id by 1
SET #NId = #NId + 1
--GENERATE ACTUAL APHANUMERIC ID HERE
SET #PId = #PId + cast(#NId AS VARCHAR)
INSERT INTO tblProduct(id)values (#PId)
END
I am gettin the following error:
Msg 8120, Level 16, State 1, Procedure spInsertInProduct, Line 10
Column 'tblProduct.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Procedure spInsertInProduct, Line 10
Column 'tblProduct.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.**
SELECT #NId = max(
cast(substring(id, 4, len(id)) as int)
)
FROM tblProduct;
This assumes your substring function is returning the numeric portion of your id. I made changes since in other examples your id's start with PRD.
Side note: There is no reason to have you Product ID's start with PRD in the database. If this were an identity field, you could set it to increment by 1 and in any display just have: 'PRD' + Cast(ID as varchar25)) as ProductID. Maybe it is not that simple of all ID's do not start with the same three letters.
Your line
SELECT #NId = cast(substring(id, 3, len(id)) as int)
FROM tblProduct
group by left(id, 2)
order by id
is not doing what you were wanting it to. It is failing because you can't include id in the select directly, because you're grouping by left(id, 2), not id itself. You cannot put something into the select statement when grouping, unless it is part of the Group By, or an aggregate (such as SUM and MAX.)
(Edit: Corrected, Left and Substring are not 0 based--to get the PRD tag and such, we need substring 4, and left 3.)
The correct way of doing this would be:
SELECT #NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)
FROM tblProduct
group by left(id, 3)
order by left(id, 3)
I have tested your stored procedure in SQL Server 2000 and Query Analyzer it works very well. Just I have removed create table code from that.