find a number that is not in the ID column - sql

Table has two columns Name and ID.
ID (int,not null)
Name (nvarchar(255),not null)
I need a SQL script that will run on a report server that will do the following:
User inputs "New.Name"
User inputs "Old.Name"
If "New.Name" AND "Old.Name" is not in Column [Name] then Print "Names Incorrect"
then return to beginning. else continue
Find a number that is not in the ID Column then Declare as #Number
Declare #NewID AS int
Declare #OldID AS int
SET #NewID = ID Where Name = New.Name
SET #OldID = ID where Name = Old.Name
UPDATE Table SET ID = #Number WHERE ID = #NewID
UPDATE Table SET ID = #NewID WHERE ID = #OldID
UPDATE Table SET ID = #OldID WHERE ID = #NewID
Is it possible to code this in SQL Server 2005 Reporting Services?
I have tried my best with my little knowledge of SQL but I am not sure what to do with the rest.

Yes. I think this is possible.
SQL Server Reporting Services accepts parameters and can pass these to a stored procedure.
These parameters can also be bound to lists which means that the NewName and OldName parameters could be populated with existing values from the Name column.
The stored procedure would need to return a result set (say with one column called result that you then display on the report)
This isn't a typical use for SSRS though and may well not be the best interface for doing this.

Related

SQL Server : get the row Identity

I have this as the first part of a stored procedure:
DECLARE #_id as int
if exists(select 1 from JTrack_Visitors WHERE cookie = #cookie)
begin
UPDATE JTrack_Visitors
SET LastSeen = #_now
WHERE cookie = #cookie
end
else
begin
INSERT INTO JTrack_Visitors(Cookie, CreatedOn, LastSeen)
VALUES (#cookie, #_now, #_now)
end
How can I set #_id to be the identity of the row either being inserted or updated? I need that value to use later in the stored procedure.
Thanks.
You can make use of OUTPUT clause in your both statements, in either case populate a table variable and later retrieve value from that table variable.
DECLARE #_id as int;
DECLARE #ID_Table TABLE(ID INT);
IF EXISTS (select 1 from JTrack_Visitors WHERE cookie = #cookie)
BEGIN
UPDATE JTrack_Visitors
SET LastSeen = #_now
OUTPUT inserted.ID INTO #ID_Table(ID)
WHERE cookie = #cookie
END
ELSE
BEGIN
INSERT INTO JTrack_Visitors(Cookie,CreatedOn,LastSeen)
OUTPUT inserted.ID INTO #ID_Table(ID)
VALUES (#cookie,#_now,#_now)
END
SELECT #_id = ID FROM #ID_Table;
Depending on the SQL Server version you're using you could use the MERGE statement including the OUTPUT clause to get the values you're looking for.
This would also eliminate the need to check for existence and either update or insert.

SQL Server UPDATE Column if Same CODE and DeptID Don't Exist

When I execute a Procedure I would like to UPDATE table1 and SET the new values for the CODE, NUMBER, and ADDRESS columns only if the same CODE and DeptID do not exist. If I change the CODE to an existing name in table1 it is OK as long as the DeptID is different.
Example:
Say I want to change Beta to Delta. That is fine because they have different DeptIDs. So I want to UPDATE everything, aka the third row in my example would now have the values (1, Delta, 'whateverNUMBER', 'whateverADDRESS')
But if I wanted to take that same third row Beta and change the CODE to Alpha I don't want to allow that and I don't want to SET the NUMBER or ADDRESS either because there is already a row with CODE Alpha and DeptID 1.
How would I be able to accomplish this?
Here is one of my attempts which does not work:
UPDATE dbo.table1
SET
CODE = #CODE
,NUMBER = #NUMBER
,ADDRESS = #ADDRESS
WHERE ID = #ID
AND NOT EXISTS
(
SELECT NAME FROM dbo.table1
WHERE NAME = #NAME
AND ID = #ID
)
This should work if you have the commas in the right place for syntax and specify the old code:
UPDATE dbo.table1
SET CODE = #CODE,
NUMBER = #NUMBER,
ADDRESS = #ADDRESS
WHERE ID = #ID AND
CODE = #OLDCODE AND
NOT EXISTS (SELECT 1
FROM dbo.table1
WHERE NAME = #NAME AND ID = #ID
);
The easiest would be to add a unique constraint for columns DeptId and Code.
This will prevent any duplicate insert as well as an update to already existing values.
The constraint will even prevent any changes performed directly against the table and not just within your update statement.

OUTPUT parameter returns a single row and not the entire column

I have a stored procedure as
create procedure p1
#id INT,
#name varchar(20) OUTPUT
as
begin
select #name = name
from table1
where id = #id;
end
on executing it, I simply get 1 single row as a value.
However if I do not use the output parameter as
create procedure p1
#id INT
as
begin
select name from table1 where id = #id;
end
I get the entire column. Note: In my table a single id can have multiple values, so ideally it should return > 1 values even with the OUTPUT parameter.
Why do I just get 1 row when using the OUTPUT parameter.
You actually don't get "one row" you get one scalar value via the output parameter because that's what you declared its type to be. varchar is a scalar value type. If you want a row set you don't need to use a parameter for it.

SQL Table Locking

I have an SQL Server locking question regarding an application we have in house. The application takes submissions of data and persists them into an SQL Server table. Each submission is also assigned a special catalog number (unrelated to the identity field in the table) which is a sequential alpha numeric number. These numbers are pulled from another table and are not generated at run time. So the steps are
Insert Data into Submission Table
Grab next Unassigned Catalog
Number from Catalog Table
Assign the Catalog Number to the
Submission in the Submission table
All these steps happen sequentially in the same stored procedure.
Its, rate but sometimes we manage to get two submission at the same second and they both get assigned the same Catalog Number which causes a localized version of the Apocalypse in our company for a small while.
What can we do to limit the over assignment of the catalog numbers?
When getting your next catalog number, use row locking to protect the time between you finding it and marking it as in use, e.g.:
set transaction isolation level REPEATABLE READ
begin transaction
select top 1 #catalog_number = catalog_number
from catalog_numbers with (updlock,rowlock)
where assigned = 0
update catalog_numbers set assigned = 1 where catalog_number = :catalog_number
commit transaction
You could use an identity field to produce the catalog numbers, that way you can safely create and get the number:
insert into Catalog () values ()
set #CatalogNumber = scope_identity()
The scope_identity function will return the id of the last record created in the same session, so separate sessions can create records at the same time and still end up with the correct id.
If you can't use an identity field to create the catalog numbers, you have to use a transaction to make sure that you can determine the next number and create it without another session accessing the table.
I like araqnid's response. You could also use an insert trigger on the submission table to accomplish this. The trigger would be in the scope of the insert, and you would effectively embed the logic to assign the catalog_number in the trigger. Just wanted to put your options up here.
Here's the easy solution. No race condition. No blocking from a restrictive transaction isolation level. Probably won't work in SQL dialects other than T-SQL, though.
I assume their is some outside force at work to keep your catalog number table populated with unassigned catalog numbers.
This technique should work for you: just do the same sort of "interlocked update" that retrieves a value, something like:
update top 1 CatalogNumber
set in_use = 1 ,
#newCatalogNumber = catalog_number
from CatalogNumber
where in_use = 0
Anyway, the following stored procedure just just ticks up a number on each execution and hands back the previous one. If you want fancier value, add a computed column that applies the transform of choice to the incrementing value to get the desired value.
drop table dbo.PrimaryKeyGenerator
go
create table dbo.PrimaryKeyGenerator
(
id varchar(100) not null ,
current_value int not null default(1) ,
constraint PrimaryKeyGenerator_PK primary key clustered ( id ) ,
)
go
drop procedure dbo.GetNewPrimaryKey
go
create procedure dbo.GetNewPrimaryKey
#name varchar(100)
as
set nocount on
set ansi_nulls on
set concat_null_yields_null on
set xact_abort on
declare
#uniqueValue int
--
-- put the supplied key in canonical form
--
set #name = ltrim(rtrim(lower(#name)))
--
-- if the name isn't already defined in the table, define it.
--
insert dbo.PrimaryKeyGenerator ( id )
select id = #name
where not exists ( select *
from dbo.PrimaryKeyGenerator pkg
where pkg.id = #name
)
--
-- now, an interlocked update to get the current value and increment the table
--
update PrimaryKeyGenerator
set #uniqueValue = current_value ,
current_value = current_value + 1
where id = #name
--
-- return the new unique value to the caller
--
return #uniqueValue
go
To use it:
declare #pk int
exec #pk = dbo.GetNewPrimaryKey 'foobar'
select #pk
Trivial to mod it to return a result set or return the value via an OUTPUT parameter.

How to deal with Stored Procedure?

Hello I am new in creating stored procedure can you help me how to do this.
Error:
Incorrect syntax near the keyword 'AS'.
Must declare scalar variable #Serial.
CREATE PROCEDURE sp_SIU
-- Add the parameters for the stored procedure here
#Serial varchar(50),
#Part varchar(50),
#Status varchar(50),
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
/*SET NOCOUNT ON;*/
-- Insert statements for procedure here
--where in my form if i enter serial number it will show select values
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
--Then if is correct it will Update Status on combobox
Update Table1 SET
Status=#Status
where SerialNumber=#SerialNumber
--then Insert Serial Number,Parnumber to Table 2
DECLARE #Count int
select #Count = Count(SerialNumber) from Table1 WHERE SerialNumber = #Serial
IF #Count = 0
BEGIN
INSERT INTO Table2 (SerialNumber,PArtNumber)
VALUES
(#Serial, #Part)
END
RETURN #Count
RETURN
Edit: Moved Updated info posted as an answer into Question
Oops my post is not that kind a miss.
It is possible to join this 3 sql string in one stored procedure?
Scenario:
{
What i have to do in my form is that i will enter serial number to txtserial.text by using the select sql it will show serialnumber,partnumber and status on lblserial.text,lblpartnumber.text and lblstatus.text.
And i will compare:
txtserial.text == lblserial.text
txtpartnumber.text == lblpartnumber.text
for my error handler.
{
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
}
Then if they are equal then:
I will update my Status from cbostatus.text if serial and part is correct then use sql upate.
{
Update Table1 SET
Status=#Status,
Modifiedby=#username,
DateModified=#Date
where SerialNumber=#Serial
}
Then insert serialnumber, using sql insert to another table.
{
INSERT INTO Table2 (SerialNumber,DateCreated,Createdby)
VALUES
(#Serial,#date,#username)
}
something likethis.
")
You have a rogue comma here
#Status varchar(50),
AS
and the name lurches between #Serial and #SerialNumber are these intended to be 2 different parameters?
Also what is the purpose of this line?
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
Currently it will just send back a 3 column result set to the calling application. Is that what it is intended to do (it doesn't seem to match the following comment which seems to imply it is meant to be some kind of check)?
Yes, you can execute 3 SQL statements inside one stored procedure. You probably want to declare some local variables inside your sproc to hold the intermediate results, i.e.
CREATE PROCEDURE BLAHBLAH
#SerialNumber VarChar(50)
AS
BEGIN
DECLARE #partnumber varchar(50);
SELECT #partnumber = partnumber FROM Table WHERE serialnumber = #SerialNumber;
...
SELECT #partnumber; --- return as recordset
RETURN #partnumber; --- return as return value
END
Then you can later insert #partnumber, test #partnumber, return #partnumber etc. I don't quite understand what you want to do; seems like you mostly want to look up a partnumber based on a serial number, but you want to do some uniqueness tests also. It would help if you could clarify the goal a bit more.
I recommend you ignore the user interface stuff for the moment. Write yourself some nice clean stored procedures that encapsulate the transaction and will do the right thing even if fired off at the same time from two different connections. Get everything working to your satisfaction in your SQL environment. Then go back to the user interface.
Oops my post is not that kind a miss.
It is possible to join this 3 sql string in one stored procedure?
Scenario:
What I have to do in my form is that I will enter serial number to txtserial.text by using the select sql it will show serialnumber,partnumber and status on lblserial.text,lblpartnumber.text and lblstatus.text.
AndI will compare:
txtserial.text == lblserial.text
txtpartnumber.text == lblpartnumber.text
for my error handler.
{
Select SerialNumber,PartNumber,Status from Table1 where SerialNUmber = #Serial
}
Then if they are equal then:
I will update my Status from cbostatus.text if serial and part is correct then use sql update.
{
Update Table1
SET Status = #Status,
Modifiedby = #username,
DateModified = #Date
where SerialNumber = #Serial
}
Then insert serialnumber, using sql insert to another table.
{
INSERT INTO Table2(SerialNumber, DateCreated, Createdby)
VALUES(#Serial, #date, #username)
}
something like this.