storing a unique value with Top is not posible Sybase - tsql

I wonder why i can not do that in sybase 15.5
My table is call "web_titles"
title_id is a varchar(6)
declare #idAux varchar(6)
set #idAux = (select top 1 title_id from web_titles)
if i just do
select top 1 title_id from web_titles
return
title_id
-----------
PC8888
but if i try to set the variable i recive
Sybase error
"Incorrect syntax near the keyword 'top' "
I dont understand why. Any idee?

To assign value to variable you could use:
declare #idAux varchar(6);
select top 1 #idAux = title_id from web_titles;
Keep in mind that TOP 1 without ORDER BY is not reliable.

TOP, ORDER BY and UNION are not allowed in subqueries in ASE

Related

Removing all the Alphabets from a string using a single SQL Query [duplicate]

I'm currently doing a data conversion project and need to strip all alphabetical characters from a string. Unfortunately I can't create or use a function as we don't own the source machine making the methods I've found from searching for previous posts unusable.
What would be the best way to do this in a select statement? Speed isn't too much of an issue as this will only be running over 30,000 records or so and is a once off statement.
You can do this in a single statement. You're not really creating a statement with 200+ REPLACEs are you?!
update tbl
set S = U.clean
from tbl
cross apply
(
select Substring(tbl.S,v.number,1)
-- this table will cater for strings up to length 2047
from master..spt_values v
where v.type='P' and v.number between 1 and len(tbl.S)
and Substring(tbl.S,v.number,1) like '[0-9]'
order by v.number
for xml path ('')
) U(clean)
Working SQL Fiddle showing this query with sample data
Replicated below for posterity:
create table tbl (ID int identity, S varchar(500))
insert tbl select 'asdlfj;390312hr9fasd9uhf012 3or h239ur ' + char(13) + 'asdfasf'
insert tbl select '123'
insert tbl select ''
insert tbl select null
insert tbl select '123 a 124'
Results
ID S
1 390312990123239
2 123
3 (null)
4 (null)
5 123124
CTE comes for HELP here.
;WITH CTE AS
(
SELECT
[ProductNumber] AS OrigProductNumber
,CAST([ProductNumber] AS VARCHAR(100)) AS [ProductNumber]
FROM [AdventureWorks].[Production].[Product]
UNION ALL
SELECT OrigProductNumber
,CAST(STUFF([ProductNumber], PATINDEX('%[^0-9]%', [ProductNumber]), 1, '') AS VARCHAR(100) ) AS [ProductNumber]
FROM CTE WHERE PATINDEX('%[^0-9]%', [ProductNumber]) > 0
)
SELECT * FROM CTE
WHERE PATINDEX('%[^0-9]%', [ProductNumber]) = 0
OPTION (MAXRECURSION 0)
output:
OrigProductNumber ProductNumber
WB-H098 098
VE-C304-S 304
VE-C304-M 304
VE-C304-L 304
TT-T092 092
RichardTheKiwi's script in a function for use in selects without cross apply,
also added dot because in my case I use it for double and money values within a varchar field
CREATE FUNCTION dbo.ReplaceNonNumericChars (#string VARCHAR(5000))
RETURNS VARCHAR(1000)
AS
BEGIN
SET #string = REPLACE(#string, ',', '.')
SET #string = (SELECT SUBSTRING(#string, v.number, 1)
FROM master..spt_values v
WHERE v.type = 'P'
AND v.number BETWEEN 1 AND LEN(#string)
AND (SUBSTRING(#string, v.number, 1) LIKE '[0-9]'
OR SUBSTRING(#string, v.number, 1) LIKE '[.]')
ORDER BY v.number
FOR
XML PATH('')
)
RETURN #string
END
GO
Thanks RichardTheKiwi +1
Well if you really can't use a function, I suppose you could do something like this:
SELECT REPLACE(REPLACE(REPLACE(LOWER(col),'a',''),'b',''),'c','')
FROM dbo.table...
Obviously it would be a lot uglier than that, since I only handled the first three letters, but it should give the idea.

Is it possible to pass a sub-query for the Default Value when adding a new column to a table?

ALTER TABLE TABLENAME
ADD New_Col3 INT NOT NULL
CONSTRAINT CONSTRAINT_1 DEFAULT {DEFAULT_VALUE}
If i am adding a new column that is not null to an existing table, is there away i can pass a t-sql sub query to provide the column's default value? Or i can only update the new column with query result value in a separate statement?
The sub-query is like below
SELECT ID FROM dbo.Category WHERE CategoryName = N'Default Category'
I think you could clarify for us a bit more about what you're doing. I'm confused. This is all that I can think of...
DECLARE #sqlstring varchar(max)=''
,#defaultValue varchar(10)='8'
SET #sqlstring=
'ALTER TABLE TABLENAME ADD New_Col8 INT NOT NULL
CONSTRAINT CONSTRAINT_8 DEFAULT (' + (SELECT TOP 1 CAST(number as varchar(2)) FROM
master..spt_values WHERE number=#defaultValue) + ')'
PRINT #sqlstring
EXEC (#sqlstring)

SQL Server, variable in IN Clause

I want to use a variable inside IN clause, similar to this:
Declare #tt NVARCHAR(MAX)
SET #tt = '02ea2b81-07f0-4660-bca1-81563f65bf65','07728975-cb1d-484c-8894-14f5b793cbef','1071ee4f-a214-443f-8694-0b3e9d2dc77e','120d2881-b04f-4707-a925-e4d941f03201','23af54a7-6666-4747-a74a-c2101cda59b0','260d2ce5-f4f0-4a0b-aa0b-3e1d2b5fcfeb','2710a913-13e7-4300-91f1-2646e2f8449e','2cebc482-4917-4aa3-973b-2481619a78e7','2d2269a4-9164-4dae-a732-90448d761509','2d29c707-1c5f-4e00-bd3c-bfd2ec2c6e29','3ead72a1-de91-47e9-8038-cc504a5274ec','40a03f53-7fd7-488d-922d-3435652219cb','43c93954-2e75-4d47-a53f-848eee609cf1','441e1a59-d397-4981-b770-01fb4594152e','4dacc9df-0536-46f6-af5d-78610ed998cd','4e4910ee-db9b-45ba-8872-2819dcefdc2c','4f9fd3ef-ba81-44bb-8c75-7cf6998e115e','60d9c73f-46c3-4ab1-9a4e-5440d18a0fd8','63e0cc57-1803-473f-847d-f3318f70c993','6510de61-9a1d-4f69-bec4-a744ea2bb847','799e2e55-2ba8-4772-8aff-331ed1817225','7be022db-4d37-4964-9005-3de7c6286027','85ba80c3-5c8b-4097-b5c9-c0d55ac6cf2f','8bc45b07-6a65-43c2-a41e-e791b085a053','8ca2d4a7-f4d6-4b56-aa41-42550e3a11b5','8fa7c3f6-e042-4b93-829f-79b8946a909e','ab34d18a-9482-4146-adb2-7e45e32f8cdd','ac43b44b-651c-4a98-a55f-82878cc8c656','ad9f222c-a98e-44eb-af9e-6f083941be9e','af7e8d24-9126-4d9b-a48a-75bf344c3529','b0e95518-0fef-46ba-81f4-0d1356ebc135','b1f1810f-3044-40b3-b218-5bb02d8922bd','b32ebf2b-f247-4032-8a37-285e4c3488a9','b93a8bb7-c62f-47b7-86ba-0421eb67ca14','c5342d7e-1667-47cb-bccf-91c5e8e9f18c','e2cf46f6-a522-4a96-8a84-f1ce3818c364','f01f4010-a192-43ca-a3bf-157379f4779d','f0f168ec-f043-41ef-90d3-3eac68b90334','f99af706-e1bb-42ba-bdf9-348a3b02c25e','fe691dee-b133-4d1c-90a3-8889cd3482d2';
Select * from table where assessmentId IN(#tt)
But this query is failing, saying Incorrect syntax near ','. The same query will work if I will not use variable in IN clause and directly pass the Id's
Select * from table where AssessmentId IN
('02ea2b81-07f0-4660-bca1-81563f65bf65','07728975-cb1d-484c-8894-14f5b793cbef','1071ee4f-a214-443f-8694-0b3e9d2dc77e','120d2881-b04f-4707-a925-e4d941f03201','23af54a7-6666-4747-a74a-c2101cda59b0','260d2ce5-f4f0-4a0b-aa0b-3e1d2b5fcfeb','2710a913-13e7-4300-91f1-2646e2f8449e','2cebc482-4917-4aa3-973b-2481619a78e7','2d2269a4-9164-4dae-a732-90448d761509','2d29c707-1c5f-4e00-bd3c-bfd2ec2c6e29','3ead72a1-de91-47e9-8038-cc504a5274ec','40a03f53-7fd7-488d-922d-3435652219cb','43c93954-2e75-4d47-a53f-848eee609cf1','441e1a59-d397-4981-b770-01fb4594152e','4dacc9df-0536-46f6-af5d-78610ed998cd','4e4910ee-db9b-45ba-8872-2819dcefdc2c','4f9fd3ef-ba81-44bb-8c75-7cf6998e115e','60d9c73f-46c3-4ab1-9a4e-5440d18a0fd8','63e0cc57-1803-473f-847d-f3318f70c993','6510de61-9a1d-4f69-bec4-a744ea2bb847','799e2e55-2ba8-4772-8aff-331ed1817225','7be022db-4d37-4964-9005-3de7c6286027','85ba80c3-5c8b-4097-b5c9-c0d55ac6cf2f','8bc45b07-6a65-43c2-a41e-e791b085a053','8ca2d4a7-f4d6-4b56-aa41-42550e3a11b5','8fa7c3f6-e042-4b93-829f-79b8946a909e','ab34d18a-9482-4146-adb2-7e45e32f8cdd','ac43b44b-651c-4a98-a55f-82878cc8c656','ad9f222c-a98e-44eb-af9e-6f083941be9e','af7e8d24-9126-4d9b-a48a-75bf344c3529','b0e95518-0fef-46ba-81f4-0d1356ebc135','b1f1810f-3044-40b3-b218-5bb02d8922bd','b32ebf2b-f247-4032-8a37-285e4c3488a9','b93a8bb7-c62f-47b7-86ba-0421eb67ca14','c5342d7e-1667-47cb-bccf-91c5e8e9f18c','e2cf46f6-a522-4a96-8a84-f1ce3818c364','f01f4010-a192-43ca-a3bf-157379f4779d','f0f168ec-f043-41ef-90d3-3eac68b90334','f99af706-e1bb-42ba-bdf9-348a3b02c25e','fe691dee-b133-4d1c-90a3-8889cd3482d2');
How can I use variable in IN clause using the first approach?
You will have to insert the values into a temp table.
Something like
DECLARE #TempTable TABLE(
assessmentId VARCHAR(50)
)
INSERT INTO #TempTable
VALUES
('02ea2b81-07f0-4660-bca1-81563f65bf65'),
('07728975-cb1d-484c-8894-14f5b793cbef'),
('1071ee4f-a214-443f-8694-0b3e9d2dc77e'),
('120d2881-b04f-4707-a925-e4d941f03201'),
('23af54a7-6666-4747-a74a-c2101cda59b0'),
('260d2ce5-f4f0-4a0b-aa0b-3e1d2b5fcfeb'),
('2710a913-13e7-4300-91f1-2646e2f8449e'),
('2cebc482-4917-4aa3-973b-2481619a78e7')
SELECT *
FROM table
where AssessmentId IN (SELECT assessmentId FROM #TempTable)
Since you want to specify multiple values, use a data type that supports multiple values (as opposed to a scalar variable). Here we're using a table variable:
Declare #tt table (value nvarchar(50) not null)
insert into #tt (value) values
('02ea2b81-07f0-4660-bca1-81563f65bf65'),('07728975-cb1d-484c-8894-14f5b793cbef'),('1071ee4f-a214-443f-8694-0b3e9d2dc77e'),
('120d2881-b04f-4707-a925-e4d941f03201'),('23af54a7-6666-4747-a74a-c2101cda59b0'),('260d2ce5-f4f0-4a0b-aa0b-3e1d2b5fcfeb'),
...
Select * from table where assessmentId IN(select value from #tt)

Column name as parameter and do sum on that in T Sql

My requirement is to send Columnname as Parameter to Stored procedure and do SUM on that Column.
I have written a small stored procedure to accept the column name as a parameter and do sum on that but I am getting an error with it.
CREATE PROCEDURE dbo.testCol
-- Add the parameters for the stored procedure here
#type as nvarchar(20),
#beginDate as smalldatetime,
#endDate as smalldatetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
select dbo.mytable.date, sum(#type) as quantity
from dbo.mytable
where dbo.mytable.Date between #beginDate AND #endDate
group by dbo.mytable.date,dbo.mytable.day
order by dbo.mytable.date
END
GO
I am getting the error as "Operand data type nvarchar is invalid for sum operator." while executing this stored procedure.
Any help much appreciated.
Thanks
You'll need to use dynamic sql to get the passed column name to be used this way in the query.
Use sp_executesql and include the column name in the string, and pass #beginDate and #endDate as parameters.
If you know the column names that are valid values, you can use CASE to avoid the evils of SQL Injection:
select dbo.mytable.date,
sum(case #type when 'QuantityColumn1' then QuantityColumn1
else QuantityColumn2 end ) as quantity
from dbo.mytable
where dbo.mytable.Date between #beginDate AND #endDate
group by dbo.mytable.date,dbo.mytable.day
order by dbo.mytable.date
If you must resort to dynamic SQL, validate your input so it can be trusted.
Yes, there is an easier way, Coolcake. Just cast the variable first like so:
CREATE TABLE FOO
(N VARCHAR(20))
SELECT * FROM DBO.FOO
INSERT INTO FOO VALUES('10')
INSERT INTO FOO VALUES('20')
INSERT INTO FOO VALUES('30')
INSERT INTO FOO VALUES('40')
INSERT INTO FOO VALUES('50')
SELECT SUM(CAST(N AS INT)) FROM FOO

In SQL Server 2000, how to delete the specified rows in a table that does not have a primary key?

Let's say we have a table with some data in it.
IF OBJECT_ID('dbo.table1') IS NOT NULL
BEGIN
DROP TABLE dbo.table1;
END
CREATE TABLE table1 ( DATA INT );
---------------------------------------------------------------------
-- Generating testing data
---------------------------------------------------------------------
INSERT INTO dbo.table1(data)
SELECT 100
UNION ALL
SELECT 200
UNION ALL
SELECT NULL
UNION ALL
SELECT 400
UNION ALL
SELECT 400
UNION ALL
SELECT 500
UNION ALL
SELECT NULL;
How to delete the 2nd, 5th, 6th records in the table? The order is defined by the following query.
SELECT data
FROM dbo.table1
ORDER BY data DESC;
Note, this is in SQL Server 2000 environment.
Thanks.
In short, you need something in the table to indicate sequence. The "2nd row" is a non-sequitur when there is nothing that enforces sequence. However, a possible solution might be (toy example => toy solution):
If object_id('tempdb..#NumberedData') Is Not Null
Drop Table #NumberedData
Create Table #NumberedData
(
Id int not null identity(1,1) primary key clustered
, data int null
)
Insert #NumberedData( data )
SELECT 100
UNION ALL SELECT 200
UNION ALL SELECT NULL
UNION ALL SELECT 400
UNION ALL SELECT 400
UNION ALL SELECT 500
UNION ALL SELECT NULL
Begin Tran
Delete table1
Insert table1( data )
Select data
From #NumberedData
Where Id Not In(2,5,6)
If ##Error <> 0
Commit Tran
Else
Rollback Tran
Obviously, this type of solution is not guaranteed to work exactly as you want but the concept is the best you will get. In essence, you stuff your rows into a table with an identity column and use that to identify the rows to remove. Removing the rows entails emptying the original table and re-populating with only the rows you want. Without a unique key of some kind, there just is no clean way of handling this problem.
As you are probably aware you can do this in later versions using row_number very straightforwardly.
delete t from
(select ROW_NUMBER() over (order by data) r from table1) t
where r in (2,5,6)
Even without that it is possible to use the undocumented %%LOCKRES%% function to differentiate between 2 identical rows
SELECT data,%%LOCKRES%%
FROM dbo.table1`
I don't think that's available in SQL Server 2000 though.
In SQL Sets don't have order but cursors do so you could use something like the below. NB: I was expecting to be able to use DELETE ... WHERE CURRENT OF but that relies on a PK so the code to delete a row is not as simple as I was hoping for.
In the event that the data to be deleted is a duplicate then there is no guarantee that it will delete the same row as CURRENT OF would have. However in this eventuality the ordering of the tied rows is arbitrary anyway so whichever row is deleted could equally well have been given that row number in the cursor ordering.
DECLARE #RowsToDelete TABLE
(
rowidx INT PRIMARY KEY
)
INSERT INTO #RowsToDelete SELECT 2 UNION SELECT 5 UNION SELECT 6
DECLARE #PrevRowIdx int
DECLARE #CurrentRowIdx int
DECLARE #Offset int
SET #CurrentRowIdx = 1
DECLARE #data int
DECLARE ordered_cursor SCROLL CURSOR FOR
SELECT data
FROM dbo.table1
ORDER BY data
OPEN ordered_cursor
FETCH NEXT FROM ordered_cursor INTO #data
WHILE EXISTS(SELECT * FROM #RowsToDelete)
BEGIN
SET #PrevRowIdx = #CurrentRowIdx
SET #CurrentRowIdx = (SELECT TOP 1 rowidx FROM #RowsToDelete ORDER BY rowidx)
SET #Offset = #CurrentRowIdx - #PrevRowIdx
DELETE FROM #RowsToDelete WHERE rowidx = #CurrentRowIdx
FETCH RELATIVE #Offset FROM ordered_cursor INTO #data
/*Can't use DELETE ... WHERE CURRENT OF as here that requires a PK*/
SET ROWCOUNT 1
DELETE FROM dbo.table1 WHERE (data=#data OR data IS NULL OR #data IS NULL)
SET ROWCOUNT 0
END
CLOSE ordered_cursor
DEALLOCATE ordered_cursor
To perform any action on a set of rows (such as deleting them), you need to know what identifies those rows.
So, you have to come up with criteria that identifies the rows you want to delete.
Providing a toy example, like the one above, is not particularly useful.
You plan ahead and if you anticipate this is possible you add a surrogate key column or some such.
In general you make sure you don't create tables without PK's.
It's like asking "Say I don't look both directions before crossing the road and I step in front of a bus."