I want help from you to create a query. I am new in software career and i am trying to developing a KBC Type Quiz Game for Windows Mobile Application. For That i want try to fetch random records from database and if one record is appear at one time after that record will not appear again. I use This query "SELECT TOP 1 * FROM Quiz ORDER BY NEWID()" but records are repeat.
My Table structure is given below.
ColumnName DataType
Id int
Que varchar(150)
Ans1 varchar(100)
Ans2 varchar(100)
Ans3 varchar(100)
TrueAns varchar(100)
I try to create a Store Procedure also which is given below
DECLARE #counter int, #randno int, #uBound int, #lBound int
SELECT #uBound = Max(Id) FROM Quiz
SELECT #lBound = Min(Id) FROM Quiz
SELECT #randno = Round(((#uBound - #lBound) * Rand() + #lBound), 0)
SET #Counter = 0
WHILE #counter = 0
BEGIN
IF EXISTS(SELECT Id FROM Quiz WHERE Id = #randno)
BEGIN
SET NOCOUNT OFF
SELECT * FROM Quiz WHERE Id = #randno
SET #counter = 1
END
ELSE
BEGIN
SELECT #randno = Round(((#uBound - #lBound -1 ) * Rand() + #lBound), 0)
END
END
but i can't get success. My Table contain this fields Que, Ans1, Ans2, Ans3, TrueAns. Please Help me for this problem. And i want to also create a web-service which return all the records
just add a column in Quiz isread as bool and set it as a default false
then make your stored procedure like it will help you to go with webservice approach
DECLARE #counter int, #randno int, #uBound int, #lBound int
SELECT #uBound = Max(Id) FROM Quiz
SELECT #lBound = Min(Id) FROM Quiz
SELECT #randno = Round(((#uBound - #lBound) * Rand() + #lBound), 0)
SET #Counter = 0
WHILE #counter = 0
BEGIN
If(( select count(*) from Quiz where isread= true)=( select count(*) from Quiz ))
BEGIN
update Quiz SET isread=false
End
IF EXISTS(SELECT Id FROM Quiz WHERE Id = #randno and isread=false )
BEGIN
update Quiz SET isread=true WHERE Id = #randno
SET NOCOUNT OFF
SELECT * FROM Quiz WHERE Id = #randno
SET #counter = 1
END
ELSE
BEGIN
SELECT #randno = Round(((#uBound - #lBound -1 ) * Rand() + #lBound), 0)
END
END
Related
I am trying to update a table using table type parameter. Currently I am using the below query. But I would like to perform update in batches having batch size as one of the parameters. Kindly help.
ALTER PROCEDURE UPDATEStatus
#Ids int ,
#numbers TypeofNumbers readonly,
#Status char(2),
#nname varchar(50),
AS
BEGIN
BEGIN TRY
update e
set
e.status = #Status,
e.user =#nname,
e.time = GETDATE()
from detailtable e
join #numbers en on en.ID =e.ID
where e.oddIDs = #Ids
I tried to do in a single update but I wanted to do in sets or batches one by one. say 100 records first and then next 100 records until all are done
You can use something like this to do your update in batches:
CREATE OR ALTER PROCEDURE UPDATEStatus
#Ids INT,
#numbers TypeOfNumbers READONLY,
#Status CHAR(2),
#nname VARCHAR(50)
AS
BEGIN
DECLARE #UpdatedRows INT;
DECLARE #Skip INT = 0;
DECLARE #BatchSize INT = 100;
WHILE ISNULL(#UpdatedRows, 1) > 0
BEGIN
WITH CTE
AS (SELECT *
FROM #numbers AS n
ORDER BY n.ID OFFSET #Skip * #BatchSize ROWS FETCH NEXT #BatchSize ROWS ONLY)
UPDATE e
SET
e.[Status] = #Status,
e.[User] = #nname,
e.[time] = GETDATE()
FROM CTE AS en
JOIN detailtable e ON en.ID = e.ID;
SET #UpdatedRows = ##ROWCOUNT;
SET #Skip = #Skip + 1;
END;
END;
GO
Next time please also provide scripts for the DDL and some testdata.
Assume i got the below row of number and max quantity value is 10.
Quantity BatchValue
2 0
4 0
4 0
6 1
8 2
Summation of 2+4+4 gives me a value less than or equal to max quatity 10 and so the batch value for those rows become 0. The pending rows are 6 and 8. They cannot be summed up to be < max quantity. So they will be seperate. Can we get an sql query or an algorith that can do this?
Here's a nice running sum routine you can use
create table #temp (rowid int identity, quantity int)
insert #temp
select quantity from yourtable order by your order
declare #holding table (quantity int, runningsum int)
declare #quantity int
declare #running int=0
declare #iterator int = 1
while #iterator<=(select max(rowid) from #temp)
begin
select #quantity=quantity from #temp where rowid=#iterator
set #running=#quantity+#running
insert #holding
select #quantity, #running
set #iterator=#iterator+1
end
Edited code from Daniel Marcus above to give the actual response requested in query.
CREATE TABLE #temp(rowid int identity(1,1), quantity int)
INSERT INTO #temp
SELECT 2
UNION ALL SELECT 4
UNION ALL SELECT 4
UNION ALL SELECT 6
UNION ALL SELECT 8
declare #batchValue int = 0 ,#maxquantity int = 10
declare #holding table (quantity int, batchvalue int)
declare #quantity int
declare #running int=0
declare #iterator int = 1
while #iterator<=(select max(rowid) from #temp)
begin
select #quantity=quantity from #temp where rowid=#iterator
set #running=#quantity+#running
-- Newly added condition
if (#running > #maxquantity) BEGIN
SET #batchValue = #batchValue + 1 -- increment the batch value
insert #holding select #quantity, #batchValue
SET #running = #quantity -- reset the running value
END
ELSE
insert #holding select #quantity, #batchValue
set #iterator=#iterator+1
end
SELECT * FROM #holding
DROP TABLE #temp
Hope the snippet works for your purpose. I tested this in SQL azure and provides the result you mentioned.
--The below query will help you if you working on sql server 2012 or higher
CREATE TABLE #RUN_TOT(ID INT)
INSERT INTO #RUN_TOT VALUES(2),(4),(4),(6),(8)
;WITH CTE AS
(
SELECT ID,
ROW_NUMBER() OVER(ORDER BY ID) RNUM,
CASE
WHEN SUM(ID) OVER(ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) <=
(SELECT MAX(ID) FROM #RUN_TOT) THEN 0
ELSE
ID
END VAL
FROM #RUN_TOT
)
SELECT ID,VAL FROM CTE WHERE VAL=0
UNION ALL
SELECT ID,ROW_NUMBER() OVER(ORDER BY VAL) VAL FROM CTE WHERE VAL<>0
I have a DB with 60 tables. In some of those tables I have a bit column named "Open" where I store a 0 if the record is not in use by an user (user access DB from a C# application) and an 1 if the record is in use.
Well, I need to get all the records from all the tables in my database where the "open" column value is true, or 1.
Is this even possible to do?
Here's a simple use of the undocumented sp_MSforeachtable:
EXEC sp_MSforeachtable
#command1='SELECT * FROM ? WHERE Open=1',
#whereand='AND o.id in (select object_id from sys.columns c where c.name=''Open'')'
Quick piece of code that gets list of tables within your database. Using a cursor loop through the answers checking it they have the fld named [open] and if it does the build a SQL statement and the execute this SQL string.
CREATE PROCEDURE usp_BulkTableOpenReport
AS
BEGIN
DECLARE #TBLS AS TABLE (REF INT IDENTITY (0,1), TABLENAME NVARCHAR(100), TABLEID BIGINT);
DECLARE #TBL AS NVARCHAR(100);
DECLARE #TBLID AS BIGINT;
DECLARE #SQL AS NVARCHAR(MAX);
DECLARE #I INT = 0;
DECLARE #M INT = 0;
DECLARE #V INT = 0
INSERT INTO #TBLS(TABLENAME,TABLEID)
SELECT NAME,OBJECT_ID FROM sys.tables
SELECT #M = MAX(REF) FROM #TBLS
WHILE #I <= #M
BEGIN
SELECT #TBL = TABLENAME, #TBLID= TABLEID FROM #TBLS WHERE REF = #I
/* CHECK TO MAKE INSURE THAT A FLD CALLED [OPEN] EXIST. */
SELECT #V = COUNT(*) FROM SYS.columns WHERE name = 'OPEN' AND OBJECT_ID = #TBLID
IF #V != 0
BEGIN
SET #SQL = 'SELECT * FROM [' + #TBL + '] WHERE [OPEN] = 1'
EXEC SP_EXECUTESQL #SQL
END;
SET #I = #I + 1
END;
END
GO
From your c# application exec the query "EXEC usp_BulkTableOpenReport" then loop through the table outputs.
I want to generate a sequence number based on the column value. I want to have this kind of output. I gonna use this in c# .net winform as GridView output
TABLE1
ID Name NoStub
1 arte 3
2 gonzake 2
TABLE2
ID Name StubNumberStart StubNumberEnd
1 arte 0001 0003
2 gonzake 0004 0005
Try this query.. it will give result from Table 2 to Table 1
DECLARE #T1 AS TABLE (ID INT, NAME VARCHAR(50), STUBNUMBER VARCHAR(10))
INSERT INTO #T1 VALUES ( 1, 'ARTE', '001')
INSERT INTO #T1 VALUES ( 1, 'ARTE', '002')
INSERT INTO #T1 VALUES ( 1, 'ARTE', '003')
INSERT INTO #T1 VALUES ( 1, 'GONZAKE', '004')
INSERT INTO #T1 VALUES ( 1, 'GONZAKE', '005')
SELECT * FROM #T1
SELECT DISTINCT ID ,NAME, COUNT(*) AS NOSTUB FROM #T1
GROUP BY ID, NAME
If your request is different from Table 1 to Table 2 then please let me know .. you will get new query...
ALTER PROCEDURE ExpandIt
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Id int;
DECLARE #name varchar(50);
DECLARE #noStub int;
DECLARE #stubNumber char(8);
DECLARE #count as int = 0;
DECLARE #continuedID as int = 0;
DECLARE t1 CURSOR FAST_FORWARD FOR
SELECT ID, Name,NoStub from Table1
OPEN t1
FETCH NEXT FROM t1 INTO #Id, #name, #noStub
WHILE ##FETCH_STATUS = 0
BEGIN
WHILE (#count < #noStub)
BEGIN
SET #count = #count + 1;
SET #stubNumber = ('0000' + CONVERT (CHAR, #continuedID + #count));
SET #stubNumber = SUBSTRING (#stubNumber,LEN(#stubNumber)-4+1, 4);
INSERT INTO Table2 (ID, Name, StubNumber)
VALUES (#Id, #name,#stubNumber);
END
SET #continuedID = #count;
SET #count = 0;
FETCH NEXT FROM t1 INTO #Id, #name, #noStub
END
CLOSE t1 ;
DEALLOCATE t1
END
I am using Silverlight and Linq-to-SQL to communicate with the database.
I have a stored procedure which receives 2 parameters (PFOID and Quantity) and Userid and returns a product name.
If we send multiple values like multiple pfoid's and quantity's it will return multiple product names shown as below
The stored procedure looks like this..
ALTER PROCEDURE [PFO].[PFOValidateUpdateData]
#PfoIDs xml, -- list of PFO ID's
#UserID uniqueidentifier --The Identity of the User making the call.
AS
BEGIN
-- SET DEFAULT BEHAVIOR
SET NOCOUNT ON -- Performance: stops rows affected messages
SET DEADLOCK_PRIORITY LOW -- This SP to be the Deadlock victim
-- Initialise Lock-Timeout and Deadlock vars for Insert
DECLARE #iLockTimeoutRetries as int
DECLARE #iDeadLockRetries as int
DECLARE #dtLockTimeoutSleepInterval as datetime
DECLARE #dtDeadlockSleepInterval as datetime
DECLARE #iErrorNumber as int
SET #iLockTimeoutRetries = 0
SET #iDeadLockRetries = 0
SET #dtLockTimeoutSleepInterval = sCommon.fnLockTimeoutSleepInterval()
SET #dtDeadlockSleepInterval= sCommon.fnDeadlockSleepInterval()
SET #iErrorNumber = 0
-- procedure specific
DECLARE #idoc as int
DECLARE #IsBrightstarUser as bit
RETRY:
BEGIN TRY
--Create Temp table to store stores!
CREATE TABLE [#PFOList]
(
[PFOId] nvarchar(50),
[Quantity] INT
)
--Create Temp table to store User stores!
CREATE TABLE [#UserStoreList]
(
[StoreID_XRef] nvarchar(50)
)
print CONVERT(varchar(1000), #PfoIDs)
--Create Document
EXEC sp_xml_preparedocument #idoc OUTPUT, #PfoIDs
-- Append to new list of Store records
INSERT INTO [#PFOList] (
[PFOId],
[Quantity]
)
SELECT [PFOID],[Quantity]
FROM OPENXML (#idoc, 'ArrayOfString/string',2)
WITH( [PFOID] nvarchar(50),[Quantity] [INT]) Stores
--WHERE [PFOId] Is Not NULL
-- Clean UP
exec sp_xml_removedocument #iDoc
-- are we dealing with a brightstar user?
SET #IsBrightstarUser = CASE WHEN exists
(SELECT *
FROM dbo.aspnet_UsersInRoles AS uir inner join
dbo.aspnet_Roles AS roles ON uir.RoleId = roles.roleid
WHERE roles.rolename = 'Brightstar Employee' and uir.userid = #userid)
THEN 1 ELSE 0 END
--Get User Storelist
INSERT INTO [#UserStoreList] (
[StoreID_XRef]
)
SELECT s.StoreId_XRef
FROM PFO.UserStoreLink us(nolock)
INNER JOIN PFO.Store s(nolock)
ON us.StoreId=s.StoreId
where UserId=#UserID
--Select * from [#PFOList]
--SELECT #IsBrightstarUser AS ISBrightstaruser
--SELECT * from [#UserStoreList]
--If BrightstarCustomer Update all the Quantities.
IF #IsBrightstarUser=1
BEGIN
UPDATE
PFO.PFO
SET
IsBrightstarReviewComplete = 1
,[ModifyingUsersID] = #UserID
,[ModifiedDate] = getdate()
,[PlannedQty] = pfol.[Quantity]
,[BrightstarReviewedQty]=pfol.[Quantity]
FROM
PFO.PFO as pfo
INNER JOIN [#UserStoreList] as stores on pfo.StoreId_XRef=stores.StoreID_XRef
INNER JOIN [#PFOList] as pfol on pfo.PFOId = pfol.PFOId
WHERE #IsBrightstarUser = 1
END
ELSE BEGIN
--Update Non Contrained Orders
UPDATE
PFO.PFO
SET
[ModifyingUsersID] = #UserID
,[ModifiedDate] = getdate()
,[PlannedQty] = pfol.[Quantity]
FROM
PFO.PFO (nolock) as pfo
INNER JOIN [#UserStoreList] as stores on pfo.StoreId_XRef=stores.StoreID_XRef
INNER JOIN [#PFOList] as pfol on pfo.PFOId = pfol.PFOId
WHERE pfo.IsBrightstarReviewComplete=1 AND IsConstraint=0
--SELECT * from PFO.PFO (nolock) where PFOId='04676723-2afb-49ff-9fa1-0131cabb407c'
--Update Contrained Orders
--Get Existing quantities for the User
CREATE TABLE #ExistingProductQuantity
(
[PfoID] nvarchar(100)
,[Product] nvarchar(255)
,[PlannedQty] INT
,[BrightstarReviewedQty] INT
)
CREATE TABLE #CustProductQuantity
(
[Product] nvarchar(255)
,[IsUpdatable] BIT
)
INSERT INTO #ExistingProductQuantity
( [PfoID],[Product],[PlannedQty],[BrightstarReviewedQty])
SELECT PFOId,InventoryId,PlannedQty,BrightstarReviewedQty
FROM PFO.PFO as pfo
INNER JOIN [#UserStoreList] as stores on pfo.StoreId_XRef=stores.StoreID_XRef
WHERE pfo.IsBrightstarReviewComplete=1 AND IsConstraint=1
UPDATE
#ExistingProductQuantity
SET [PlannedQty]=pfol.[Quantity]
FROM #ExistingProductQuantity eoq
INNER JOIN [#PFOList] as pfol on eoq.PFOId = pfol.PFOId
INSERT INTO #CustProductQuantity
( [Product],[IsUpdatable] )
SELECT
[Product],
CASE WHEN SUM(PlannedQty)<=SUM(BrightstarReviewedQty) THEN 1 ELSE 0 END
FROM #ExistingProductQuantity
GROUP BY [Product]
--SELECT * from #ExistingProductQuantity
--SELECT * from #CustProductQuantity
--Update the products that can be updatable
UPDATE
PFO.PFO
SET
[ModifyingUsersID] = #UserID
,[ModifiedDate] = getdate()
,[PlannedQty] = pfol.[Quantity]
FROM
PFO.PFO as pfo
INNER JOIN #UserStoreList as stores on pfo.StoreId_XRef=stores.StoreID_XRef
INNER JOIN #PFOList as pfol on pfo.PFOId = pfol.PFOId
INNER JOIN #CustProductQuantity as pr on pr.Product=pfo.InventoryId
WHERE pfo.IsBrightstarReviewComplete=1 AND pr.IsUpdatable=1 AND IsConstraint=1
--Return the products that are not updatabele
select [Product]
FROM #CustProductQuantity
where [IsUpdatable]=0
END
END TRY
BEGIN CATCH
-- Get the ErrorNumber
Set #iErrorNumber = ERROR_NUMBER()
--Handle Deadlock situation (Deletes, Inserts & Updates)
IF #iErrorNumber = 1205
BEGIN
-- If we have not made enough attempts to break the lock
IF #iDeadLockRetries < sCommon.fnMaxDeadlockRetries()
BEGIN
-- Increment the Attempt count
SET #iDeadLockRetries = #iDeadLockRetries + 1
-- Pause to allow the deadlock contention to clear
WAITFOR DELAY #dtDeadlockSleepInterval
GOTO RETRY
END
END
-- Handle Lock Timeout situation (Deletes, Inserts & Updates)
IF #iErrorNumber = 1222
BEGIN
-- If we have not made enough attempts to break the Deadlock
IF #iLockTimeoutRetries < sCommon.fnMaxLockTimeoutRetries()
BEGIN
-- Increment the Attempt count
SET #iLockTimeoutRetries = #iLockTimeoutRetries + 1
-- Pause to allow the lock contention to clear
WAITFOR DELAY #dtLockTimeoutSleepInterval
GOTO RETRY
END
END
exec Common.RethrowError
END CATCH
END
The result is as follows..
Product
6435LVWK-360-CD819E3
NSCHI535C1097I360-4C
NSCHU485C1819I360-0C
Return Value
0
My Linq-to-SQL connection is like this
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="PFO.PFOValidateUpdateData")]
public int PFOValidateUpdateData([global::System.Data.Linq.Mapping.ParameterAttribute(Name = "PfoIDs", DbType = "Xml")] System.Xml.Linq.XElement pfoIDs, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "UserID", DbType = "UniqueIdentifier")] System.Nullable<System.Guid> userID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), pfoIDs, userID);
return ((int)(result.ReturnValue));
}
I am trying to retrieve all the data from the stored procedure but the when I debugging it the return value is "o"..
I would be grateful to you if you could help me retrieve all the data returned by the stored procedure... thank you very much...
If your stored procedure returns a collection of nvarchar's, then the signature of your Linq2Sql method is not correct. It should not return an int, but an ISingleResult.
So the correct signature will be:
public ISingleResult<string> PFOValidateUpdateData(...)
{
IExecuteResult result = this....;
return (ISingleResult<string>)result.ReturnValue;
}
var products = PFOValidateUpdateData(...).ToList();
If you want to return the results from multiple SELECT's in your stored procedure, you'll have to use IMultipleResults.
Well I know this is not the right way...for time being,its working for me...
I created an other table with two columns one ProductId and ID, I am inserting the values returned by the stored procedure,
in the designer.cs I am returning the table,
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="PFO.PFOValidateUpdateData")]
public ISingleResult<PFOValidData> PFOValidateUpdateData([global::System.Data.Linq.Mapping.ParameterAttribute(Name = "PfoIDs", DbType = "Xml")] System.Xml.Linq.XElement pfoIDs, [global::System.Data.Linq.Mapping.ParameterAttribute(Name = "UserID", DbType = "UniqueIdentifier")] System.Nullable<System.Guid> userID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), pfoIDs, userID);
return ((ISingleResult<PFOValidData>)(result.ReturnValue));
}
And in the Domainservice
List<string> PFOValidateUpdateData(string pfoIds, Guid userID)
{
List<string> productIdList = new List<string>();
// Acquire the int
result = this.DataContext.PFOValidateUpdateData(element, userID);
foreach (var item in result)
{
productIdList.Add(item.ProductID);
}
return productIdList;
To get the multiple values returned by the stored procedure....
Please let me know if there is a better way to solve this... thank you