Integridad referencial con fk ciclica

07/12/2007 - 12:25 por Pablo Roca | Informe spam
Hola tengo una tabla de roles, que un registro puede ser padre de otros.
Está creada asi:

CREATE TABLE [dbo].[roles](
[pk_roles_id] [int] IDENTITY(1,1) NOT NULL,
[nombre] [varchar](30) NOT NULL CONSTRAINT [df_roles_nombre] DEFAULT (''),
[fk_pk_roles_id] [int] NULL,
CONSTRAINT [pk_roles_id] PRIMARY KEY CLUSTERED
(
[pk_roles_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY =
OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[roles] WITH CHECK ADD CONSTRAINT [fk_roles_roles_id]
FOREIGN KEY([fk_pk_roles_id])
REFERENCES [dbo].[roles] ([pk_roles_id])
GO
ALTER TABLE [dbo].[roles] CHECK CONSTRAINT [fk_roles_roles_id]

Si me voy a modificar la relacion, no me deja modificar las reglas de
actualizazion ni eliminacion . Queria ponerlas en cascada.

Alguna pista en lo que tengo mal diseñado o que debo poner?


Saludos,

Pablo Roca
La Coruna - Spain
http://www.portalfox.com

Preguntas similare

Leer las respuestas

#11 Pablo Roca
07/12/2007 - 19:51 | Informe spam
Hola Alejandro

CTE?

Uso SQL Server 2005. Y como haria la llamada al proicedimniento almacenado?
Me podrias indicarlo


Saludos,

Pablo Roca
La Coruna - Spain
http://www.portalfox.com
Respuesta Responder a este mensaje
#12 Pablo Roca
07/12/2007 - 19:52 | Informe spam
Coñe .. es verdad. Gracias Max


Saludos,

Pablo Roca
La Coruna - Spain
http://www.portalfox.com
Respuesta Responder a este mensaje
#13 Pablo Roca
07/12/2007 - 19:55 | Informe spam
Digo Gustavo :)


Saludos,

Pablo Roca
La Coruna - Spain
http://www.portalfox.com
Respuesta Responder a este mensaje
#14 Carlos M. Calvelo
07/12/2007 - 20:33 | Informe spam
Hola Pablo,

On 7 dec, 19:49, "Pablo Roca" wrote:
Bueno .. ahora lo cambié un poco mas

1. Le prohibi valores null en el campo fk_pk_roles_id
2. Le añadi una restriccion de 0 como valor por defecto al mismo campo
3. modificado el trigger de borrado para que cuando no sea un elemento padre
que no haga la segunda select

DELETE FROM [dbo].[roles] WHERE fk_pk_roles_id = 0 AND fk_pk_roles_id IN
(SELECT pk_roles_id FROM deleted)




Estás estructurando un arbol. Y un arbol tiene dos
tipos de elementos, los nodos y los enlaces.
Estos dos tipos de entidades los tienes en una tabla.
La necesidad del null (o 0 por defecto) es un signo
de ello.

Considera esta estructura:

Roles (roleid, nombre)
pk: {roleid}

Enlaces (IDPadre, IDHijo)
pk: {IDPadre,IDHijo}
fk: IDPadre -> Roles(roleid)
fk: IDHijo -> Roles(roleid)

Aquí no hay nullos ni 0 por defecto y seguro que va
a simplificar bastante todo tipo de consultas.

Como ejemplo mira este arbol y su representación
en tablas:

A
+--> B
| +--> C
| +--> D
| | +--> E
| +--> F
+--> G
+--> H

nodos enlaces
A A,B
B A,G
C B,C
D B,D
E B,F
F G,H
G D,E
H

Piensalo!

Saludos,
Carlos
Respuesta Responder a este mensaje
#15 Alejandro Mesa
07/12/2007 - 20:49 | Informe spam
Pablo,

Tambien puedes usar la logica en el triger, pero yo prefiero dejar la
restriccion de clave foranea para enforzar la integridad referencial.

USE tempdb
GO

CREATE TABLE [dbo].[roles](
[pk_roles_id] [int] IDENTITY(1,1) NOT NULL,
[nombre] [varchar](30) NOT NULL CONSTRAINT [df_roles_nombre] DEFAULT (''),
[fk_pk_roles_id] [int] NULL,
CONSTRAINT [pk_roles_id] PRIMARY KEY CLUSTERED
(
[pk_roles_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY =
OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[roles] WITH CHECK ADD CONSTRAINT [fk_roles_roles_id]
FOREIGN KEY([fk_pk_roles_id])
REFERENCES [dbo].[roles] ([pk_roles_id])
GO

ALTER TABLE [dbo].[roles] CHECK CONSTRAINT [fk_roles_roles_id]
GO

INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('Microsoft SQL Server',
NULL)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 6.5', 1)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 7', 1)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 2000', 1)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 2005', 1)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 2008', 1)
INSERT INTO dbo.roles(nombre, fk_pk_roles_id) VALUES('SS 2008 EE', 6)

SELECT * FROM dbo.roles
GO

CREATE PROCEDURE dbo.DelTree
@pk_roles_id INT
AS
SET NOCOUNT ON

CREATE TABLE #t([pk_roles_id] INT PRIMARY KEY, [fk_pk_roles_id] INT)

;WITH Tree
AS
(
SELECT [pk_roles_id], [fk_pk_roles_id]
FROM [dbo].[roles]
WHERE [pk_roles_id] = @pk_roles_id

UNION ALL

SELECT c.[pk_roles_id], c.[fk_pk_roles_id]
FROM dbo.roles AS c INNER JOIN Tree AS p ON c.[fk_pk_roles_id] =
p.[pk_roles_id]
)
INSERT INTO #t([pk_roles_id], [fk_pk_roles_id])
SELECT [pk_roles_id], [fk_pk_roles_id]
FROM [Tree]

DELETE r
FROM dbo.roles AS r INNER JOIN #t AS t ON r.[pk_roles_id] = t.[pk_roles_id]

IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO

EXEC dbo.[DelTree] @pk_roles_id = 6
GO

SELECT *
FROM dbo.roles
GO

DROP PROCEDURE dbo.[DelTree]
GO

DROP TABLE [dbo].[roles]
GO


AMB


"Pablo Roca" wrote:

Hola Alejandro

CTE?

Uso SQL Server 2005. Y como haria la llamada al proicedimniento almacenado?
Me podrias indicarlo


Saludos,

Pablo Roca
La Coruna - Spain
http://www.portalfox.com



Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida