пятница, 3 февраля 2017 г.

t-SQL. строку в столбец.

по ходу работы потребовалось вставить строку в t-sql выражение IN. например, на входе есть такая строка: "0001,0808,6695,1234,6578" или подобное.
как следствие родилась небольшая табличная функция.
длину более 10 элементов на скорость работы не проверял.

ну и длина единичного элемента не более varchar(10). ибо в задаче длина 4.

create function dbo.fn_splitFlyingNumbersXML(@str varchar(512),@delimiter varchar(1))
RETURNS @retTbl TABLE (number varchar(4) )
as begin
DECLARE @xml as xml
set @str=replace(@str,' ','')
SET @xml = cast((''+replace(@str,@delimiter ,'')+'') as xml)
insert @retTbl
SELECT case when (len(N.value('.', 'varchar(4)'))<4 len="" p="" then="" value="" varchar=""> else N.value('.', 'varchar(4)') end as value FROM @xml.nodes('X') as T(N)
return
end
go

используется вот так: 
select * from Numbers where number in (select * from 
dbo.fn_splitFlyingNumbersXML('0001,0808,6695,1234,6578')
)

вариант с разделителем:
create function [dbo].[fn_splitStringXML](@str varchar(512),@delimiter varchar(1))
RETURNS @retTbl TABLE (number varchar(10) )
as begin
DECLARE @xml as xml
set @str=replace(@str,' ','')
SET @xml = cast((''+replace(@str,@delimiter ,'')+'') as xml)
insert @retTbl
SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N)
return
end 

воскресенье, 22 июля 2012 г.

Версия MS SQL Server'а

 SELECT SERVERPROPERTY('productversion') AS Version, SERVERPROPERTY ('productlevel') AS Level, SERVERPROPERTY ('edition') AS Edition

понедельник, 5 марта 2012 г.

Удаляем повторяющиеся(дублирующиеся) записи в таблице

код ниже находит/удаляет все повторяющие записи в таблице Analitika, где дублируется поле DocId

With CTE as
(SELECT RANK() OVER (PARTITION BY Docid ORDER BY num) as rnk, *
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY Docid) num
FROM Analitika
) X
)
-- select * from CTE; -- просмотр данных
delete from CTE where rnk>1; -- удаление повторов.

среда, 6 октября 2010 г.

поиск значения по всем полям всех таблиц БД(MS SQL Server 2000-2008)

если что то надо не забыть и что может внезапно понадобиться, лучше в блоге записать))))

задача: найти значение внутри таблиц БД. и вернуть таблицу и название поля.

погуглив нашел процедуру
итого:
1) вызываем как обычную процедуру с одним параметром(имеющие руки допилят сами)
EXEC SearchAllTables 'ООО "СС-КРАЙС"'
2) код процедуры:
CREATE PROC SearchAllTables
(
@SearchStr nvarchar(100)
)
AS
BEGIN
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)

WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN
SET @ColumnName =
(
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2)
AND TABLE_NAME = PARSENAME(@TableName, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
AND QUOTENAME(COLUMN_NAME) > @ColumnName
)

IF @ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630)
FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
)
END
END
END

SELECT ColumnName, ColumnValue FROM #Results
END

пятница, 2 июля 2010 г.

Аналог Limit из MySQL в MS SQL

потребовалось реализовать аналог Limit из mysql. решил сделать процедурой. в дальнейшем добавлю список возвращаемых полей. пока что надо указать:
1) с какой записи выбираем
2) сколько записей выбираем
3) таблица
4) порядок сортировки в таблице
create PROCEDURE LimitRN ( @Begin varchar(100), @Top varchar(100), @Table varchar(max), @Sort varchar(max))
AS
DECLARE @EndSelect varchar(10), @BeginSelect varchar(10), @SQL nvarchar(max), @SSort varchar(max), @tTable varchar(max)
set @tTable=@Table
set @SSort=@Sort
set @EndSelect=@Begin+@Top
set @BeginSelect=@Begin
if @SSort=''
begin
set @SSort='(select 1)'
end
SET @SQL = 'select * from ( select row_number() over(order by '+@SSort+') as aaa, * from '+@tTable+' t ) q where aaa between '+@BeginSelect+' and '+@EndSelect
exec(@SQL)
go

понедельник, 5 апреля 2010 г.

Исходный код триггера

в предыдущем посте писал про получение списка триггеров. помимо самого списка потребовалось выдрать исходный код триггера.
рассмотрел 2 варианта:
1) получить из таблицы syscomments. это поле text.
+: можно использовать в общем запросе
-: нечитабельно
2) использовать процедуру sp_helptext, например:
exec sp_helptext @objName='TR_CommentDelete'
+: получаем читабельный код, каким он и был при создании триггера
-: выводится построчно. не думаю что это большой минус, но на вкус и цвет

воскресенье, 21 марта 2010 г.

получить все триггеры БД MS SQL Server

недавно столкнулся со следующей проблемкой:
надо получить список триггеров по определенной БД(зачем это было надо, наверное позже напишу).
в итоге делаем следующее
открываем новый запрос в SQL Server Management Studio.
Выбираем нужную БД, или указываем кодом, например: Use PayDox.
и вставляем код. я использовал вот такой
select so1.name,so.name ,sc.id, sc.text from syscomments sc, sysobjects so, sysobjects so1 where sc.id=so.id and so.name like '%TR%' and so1.id=so.parent_obj
зы: код не оптимизировал.
на выходе получаем:
1) название таблицы, которую мониторит триггер
2) Название триггера
3) Его ИД
4) код триггера

зы: код триггера разбит на несколько записей... с чем связано не знаю, ибо если не знали какой текст будут вставлять в поле то указали бы например varchar(max)

зыы: полазив по sysobjects и syscommnets много интересного и полезного можно найти.