MS SQL

12 отговора 416 прегледа
#1

MS SQL

Как да намеря columns на PRIMARY KEY с някакъв по-опростен SQL script.
Опитвах със SP ..., ама не ми харесва :(

MS SQL7, SQL2000

Отговор
в отговор на planik #2

Re: MS SQL

не разбирам какво искаш да намериш ?

[линк]
Отговор
в отговор на Topбaлaн #3

Re: MS SQL

ами всички колони които се включват в PRIMARY KEY за всяка една таблица, и това да стане с прост SQL израз.

Отговор
в отговор на planik #4

Re: MS SQL

ползвай функцията index_col. В буукс онлайн има пример.

аз имам процедура, която връща реверс-инжинирва ДДЛ-а на даден индекс -- ако искаш ще ти я е-мейлна.

Отговор
в отговор на бaй Любo #5

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]

Отговор
в отговор на planik #6

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

Отговор
в отговор на бaй Любo #7

поправка

последния селект не съм го пейстнал:

1> select name, sysstat2&8 from sysobjects where name='tst'
2> go
name
------------------------------ -----------
tst 8

Отговор
в отговор на бaй любo #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'

Отговор
в отговор на planik #9

мама им стара майкрософтска

Ще ни вземат хляба с тия усъвършенствания.

Радвам се че си намерил по-елегантно решение.

Отговор
в отговор на planik #10

що да не работи?

снощи го тествах на мс сял, работи и още как:
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,

Отговор
в отговор на baj L\bo #11

Re: що да не работи?

това работи. извинявай, може би в предишните examples нещо съм пропуснал. признавам че сега твоят скрипт ми харесва доста повече. много е добро.

Отговор
в отговор на planik #12

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

Отговор
в отговор на planik #13

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)+','

Имай предвид че нямам под ръка мс сял и не съм го тествал --

Отговор