MS SQL
12 отговора
416 прегледа
MS SQL
Как да намеря columns на PRIMARY KEY с някакъв по-опростен SQL script.
Опитвах със SP ..., ама не ми харесва :(
MS SQL7, SQL2000
Опитвах със SP ..., ама не ми харесва :(
MS SQL7, SQL2000
Re: MS SQL
ами всички колони които се включват в PRIMARY KEY за всяка една таблица, и това да стане с прост SQL израз.
Re: MS SQL
ползвай функцията index_col. В буукс онлайн има пример.
аз имам процедура, която връща реверс-инжинирва ДДЛ-а на даден индекс -- ако искаш ще ти я е-мейлна.
аз имам процедура, която връща реверс-инжинирва ДДЛ-а на даден индекс -- ако искаш ще ти я е-мейлна.
Re: MS SQL
ами гледах index_col обаче не виждам как ще ми помогне. иска ми се да намеря нещо по-простичко (SQL script), така, че да мога да го ползвам в CURSOR за да събера полетата на PRIMARY KEY на дадена таблица.
например:
DECLARE pkc CURSOR ... FOR
SELECT ????????? (тук ми е болката) WHERE ...= tblName
FETCH ...
WHILE @@FETCH_STATUS = 0
BEGIN
SET @strPKeys = @strPKeys + .........
FETCH ...
END
като резултат за табл. tblName например
SELECT @strPKeys
----------------------------------------
CompanyID, DocumentNo, DocDate and etc.
а за процедурата, може да ми я пратиш. Може да ме светне за нещо :)
[email protected]
например:
DECLARE pkc CURSOR ... FOR
SELECT ????????? (тук ми е болката) WHERE ...= tblName
FETCH ...
WHILE @@FETCH_STATUS = 0
BEGIN
SET @strPKeys = @strPKeys + .........
FETCH ...
END
като резултат за табл. tblName например
SELECT @strPKeys
----------------------------------------
CompanyID, DocumentNo, DocDate and etc.
а за процедурата, може да ми я пратиш. Може да ме светне за нещо :)
[email protected]
Re: MS SQL
ето ти тест-кейз:
create table tst (a int, b int, c int)
go
alter table tst add constraint tst_pk primary key (a,b)
go
Значи тоя констрейнт създава по същество клъстерен индекс, който е индид=1:
1> select name, keycnt from sysindexes where id=object_id('tst') and indid=1
2> go
name keycnt
------------------------------ ------
tst_pk 2
Полето кеъцнт показва колко колони има в индекса (а и б =2)
Долния скрипт връща колоните на индекса по една на ред. Ако ги искаш на един ред можеш да си инициализираш още една променлива аллкол и цикъла да правиш
селецт аллкол=аллкол+", "+индех_цол(...)
1> declare @i int, @keycnt int
2> select @i=1, @keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
3> while @i<=@keycnt
4> begin
5> select index_col('tst',1,@i)
6> select @i=@i+1
7> end
8> go
(1 row affected)
------------------------------
a
(1 row affected)
(1 row affected)
------------------------------
b
(1 row affected)
(1 row affected)
Сега цялата работа е за сайбейс но би трябвало да върви без проблеми на МС СЯЛ сервер. Провери все пак кво има в sysindexes.keycnt
Второ, има начин да направиш констрейнта да не е клъстерен индекс. Ако твоя случай е такъв, хубаво е да знаеш името на констрейнта и да търсиш в съсиндеьсис по име. Ако ли не, sysobjects.sysstat2 pokazwa `e tablicata ima primary key constraint:
name
------------------------------ -----------
tst 8
обаче нямам време сега да търся как да му се намери името.
HTH
create table tst (a int, b int, c int)
go
alter table tst add constraint tst_pk primary key (a,b)
go
Значи тоя констрейнт създава по същество клъстерен индекс, който е индид=1:
1> select name, keycnt from sysindexes where id=object_id('tst') and indid=1
2> go
name keycnt
------------------------------ ------
tst_pk 2
Полето кеъцнт показва колко колони има в индекса (а и б =2)
Долния скрипт връща колоните на индекса по една на ред. Ако ги искаш на един ред можеш да си инициализираш още една променлива аллкол и цикъла да правиш
селецт аллкол=аллкол+", "+индех_цол(...)
1> declare @i int, @keycnt int
2> select @i=1, @keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
3> while @i<=@keycnt
4> begin
5> select index_col('tst',1,@i)
6> select @i=@i+1
7> end
8> go
(1 row affected)
------------------------------
a
(1 row affected)
(1 row affected)
------------------------------
b
(1 row affected)
(1 row affected)
Сега цялата работа е за сайбейс но би трябвало да върви без проблеми на МС СЯЛ сервер. Провери все пак кво има в sysindexes.keycnt
Второ, има начин да направиш констрейнта да не е клъстерен индекс. Ако твоя случай е такъв, хубаво е да знаеш името на констрейнта и да търсиш в съсиндеьсис по име. Ако ли не, sysobjects.sysstat2 pokazwa `e tablicata ima primary key constraint:
name
------------------------------ -----------
tst 8
обаче нямам време сега да търся как да му се намери името.
HTH
поправка
последния селект не съм го пейстнал:
1> select name, sysstat2&8 from sysobjects where name='tst'
2> go
name
------------------------------ -----------
tst 8
1> select name, sysstat2&8 from sysobjects where name='tst'
2> go
name
------------------------------ -----------
tst 8
Re: поправка
нещо не действат тези scripts в MS SQL, но да си призная вече намерих доста елегантно решение (не е мое).
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID('[' + CONSTRAINT_NAME + ']'), 'IsPrimaryKey') =1
AND TABLE_NAME = 'tst'
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID('[' + CONSTRAINT_NAME + ']'), 'IsPrimaryKey') =1
AND TABLE_NAME = 'tst'
мама им стара майкрософтска
Ще ни вземат хляба с тия усъвършенствания.
Радвам се че си намерил по-елегантно решение.
Радвам се че си намерил по-елегантно решение.
що да не работи?
снощи го тествах на мс сял, работи и още как:
select @@version
go
use tempdb
go
create table tst (a int not null, b int not null, c int)
go
alter table tst add constraint tst_pk primary key (a,b)
go
select name, keycnt from sysindexes where id=object_id('tst') and indid=1
go
declare @i int, @keycnt int, @allcol varchar(255)
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
while @i<=@keycnt
begin
select @allcol=@allcol+index_col('tst',1,@i)+','
select @i=@i+1
end
select @allcol
go
output:
Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Personal Edition on Windows NT 5.0 (Build 2195: Service Pack 1)
....
a,b,
select @@version
go
use tempdb
go
create table tst (a int not null, b int not null, c int)
go
alter table tst add constraint tst_pk primary key (a,b)
go
select name, keycnt from sysindexes where id=object_id('tst') and indid=1
go
declare @i int, @keycnt int, @allcol varchar(255)
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
while @i<=@keycnt
begin
select @allcol=@allcol+index_col('tst',1,@i)+','
select @i=@i+1
end
select @allcol
go
output:
Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Personal Edition on Windows NT 5.0 (Build 2195: Service Pack 1)
....
a,b,
Re: що да не работи?
това работи. извинявай, може би в предишните examples нещо съм пропуснал. признавам че сега твоят скрипт ми харесва доста повече. много е добро.
Re: що да не работи?
продължавам. работи ти скрипта, обаче се оказва (не знам защо) че върху определена таблица (от моите с доста сложна структура) не показва нищо (NULL).
ето как съм го модифицирал (така не връща резултат):
select @@version
go
use tempdb
go
if not object_id('tst') is null drop table tst
go
CREATE TABLE [tst] (
[ID0] [int] NOT NULL ,
[ID1] [int] NOT NULL ,
[ID2] [int] NOT NULL ,
[Podelenie1] [int] NOT NULL ,
[Nomer] [decimal](10, 0) NOT NULL ,
[Data] [datetime] NOT NULL ,
[SP_SmetkaID] [int] NOT NULL ,
[Statia3] [int] NOT NULL ,
[Podelenie4] [int] NOT NULL ,
[Partida2] [int] NOT NULL ,
[DokumentNo] [decimal](10, 0) NOT NULL ,
[DataDokument] [datetime] NULL ,
[IkonElementID] [int] NOT NULL ,
[SP_SmetkaIDSub] [int] NOT NULL ,
[DokumentNoSub] [decimal](10, 0) NOT NULL ,
[DataDokumentSub] [datetime] NULL ,
[MOLNashIDSub] [int] NOT NULL ,
[SMCIdSub] [int] NOT NULL ,
[Kol] [decimal](18, 5) NOT NULL ,
[KOP] [varchar] (4) NOT NULL ,
[Kol2] [decimal](18, 5) NOT NULL ,
[Status] [bit] NOT NULL ,
[percentr] [decimal](6, 5) NOT NULL ,
[DtSkaRazp] [int] NOT NULL ,
[KolRazp] [decimal](18, 5) NOT NULL ,
[Kol2Razp] [decimal](18, 5) NOT NULL ,
[IsOk] [bit] NULL ,
[IsOkRazp] [bit] NOT NULL ,
[ID3] [int] NOT NULL )
go
alter table [tst] add CONSTRAINT [Първичен ключ по ID0,ID1,ID2,ID3, Поделение1 и дата] PRIMARY KEY NONCLUSTERED
( [ID0],
[ID1],
[ID2],
[ID3],
[Podelenie1],
[Data]
)
go
select name, keycnt from sysindexes where id=object_id('tst') and indid=1
go
declare @i int, @keycnt int, @allcol varchar(255)
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
while @i<=@keycnt
begin
select @allcol=@allcol+index_col('tst',1,@i)+','
select @i=@i+1
end
select @allcol
go
ето как съм го модифицирал (така не връща резултат):
select @@version
go
use tempdb
go
if not object_id('tst') is null drop table tst
go
CREATE TABLE [tst] (
[ID0] [int] NOT NULL ,
[ID1] [int] NOT NULL ,
[ID2] [int] NOT NULL ,
[Podelenie1] [int] NOT NULL ,
[Nomer] [decimal](10, 0) NOT NULL ,
[Data] [datetime] NOT NULL ,
[SP_SmetkaID] [int] NOT NULL ,
[Statia3] [int] NOT NULL ,
[Podelenie4] [int] NOT NULL ,
[Partida2] [int] NOT NULL ,
[DokumentNo] [decimal](10, 0) NOT NULL ,
[DataDokument] [datetime] NULL ,
[IkonElementID] [int] NOT NULL ,
[SP_SmetkaIDSub] [int] NOT NULL ,
[DokumentNoSub] [decimal](10, 0) NOT NULL ,
[DataDokumentSub] [datetime] NULL ,
[MOLNashIDSub] [int] NOT NULL ,
[SMCIdSub] [int] NOT NULL ,
[Kol] [decimal](18, 5) NOT NULL ,
[KOP] [varchar] (4) NOT NULL ,
[Kol2] [decimal](18, 5) NOT NULL ,
[Status] [bit] NOT NULL ,
[percentr] [decimal](6, 5) NOT NULL ,
[DtSkaRazp] [int] NOT NULL ,
[KolRazp] [decimal](18, 5) NOT NULL ,
[Kol2Razp] [decimal](18, 5) NOT NULL ,
[IsOk] [bit] NULL ,
[IsOkRazp] [bit] NOT NULL ,
[ID3] [int] NOT NULL )
go
alter table [tst] add CONSTRAINT [Първичен ключ по ID0,ID1,ID2,ID3, Поделение1 и дата] PRIMARY KEY NONCLUSTERED
( [ID0],
[ID1],
[ID2],
[ID3],
[Podelenie1],
[Data]
)
go
select name, keycnt from sysindexes where id=object_id('tst') and indid=1
go
declare @i int, @keycnt int, @allcol varchar(255)
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=1
while @i<=@keycnt
begin
select @allcol=@allcol+index_col('tst',1,@i)+','
select @i=@i+1
end
select @allcol
go
Re: що да не работи?
Както споменах в един от предишните постинги, когато констрейнта не е клъстерен индекс, нещата малко се променят. По същество, индид вече не е 1, а две щото неклъстерните индекси се номерират от две. Предлагам ти следните промени:
1. Дай име на констрейнта. Както си го оставил то му генерира автоматично име и ние не го знаеме:
alter table [tst] add CONSTRAINT [tst_pk]
PRIMARY KEY NONCLUSTERED
( [ID0],
[ID1],
[ID2],
[ID3],
[Podelenie1],
[Data]
)
2. Вземи му номера на индекса в една променлива. То се 2, но за да го направиш по-общо (да работи и в случайте когато създаваш таблицата, създаваш някакъв индекс и чак след това създаваш констрейнта) си го вземи номера изрично:
declare @indid int
select @indid=indid from sysindexes where id=object_id('tst') and name = 'tst_pk'
3. Използвай @индид вместо 1 в следните две изречения (оператора?):
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=@indid
select @allcol=@allcol+index_col('tst',@indid,@i)+','
Имай предвид че нямам под ръка мс сял и не съм го тествал --
1. Дай име на констрейнта. Както си го оставил то му генерира автоматично име и ние не го знаеме:
alter table [tst] add CONSTRAINT [tst_pk]
PRIMARY KEY NONCLUSTERED
( [ID0],
[ID1],
[ID2],
[ID3],
[Podelenie1],
[Data]
)
2. Вземи му номера на индекса в една променлива. То се 2, но за да го направиш по-общо (да работи и в случайте когато създаваш таблицата, създаваш някакъв индекс и чак след това създаваш констрейнта) си го вземи номера изрично:
declare @indid int
select @indid=indid from sysindexes where id=object_id('tst') and name = 'tst_pk'
3. Използвай @индид вместо 1 в следните две изречения (оператора?):
select @i=1
, @allcol=' '
,@keycnt=keycnt from sysindexes where id=object_id('tst') and indid=@indid
select @allcol=@allcol+index_col('tst',@indid,@i)+','
Имай предвид че нямам под ръка мс сял и не съм го тествал --