127 messaggi dal 06 giugno 2011
Ciao a tutti non so se sono OT , sto utilizzanto entity framework code first per effettuare le migrazioni del mio db, ho aggiunto alcune colonne e adesso quando effettuo la migrazione mi da questo messaggio:

Avviso: la tabella "NomeMiaTabella" è stata creata ma le dimensioni massime delle righe superano il valore massimo consentito, pari a 8060 byte. Le operazioni INSERT o UPDATE eseguite su questa tabella avranno esito negativo se le dimensioni delle righe risultanti superano il limite massimo consentito.

sql serve ha un limite nella gestione delle colonne? questa tabella ha circa 385 colonne ma aumenteranno, tra cui molti nvarchar(max) so che per ogni char sono 2byte , per un bit è 1 byte per un bigint sono 8 byte, ma i nvarchar non sono dinamici, cioè in base ai caratteri che inserisco?

Di seguito il mio script per la generazione della tabella dove mi esce l'errore, se tolgo l'ultima proprietà (LetteraRiferimentoOrdineCliente) ancora rientro nella dimensione massima.

Le dimensioni dei nvarchar non dovrebbero essere a zero se sono vuoti? In base a cosa conteggia questi byte?

CREATE TABLE [dbo].Prova6(
  [Id] [uniqueidentifier] NOT NULL,
  [FatturaBlocco] [bit] NOT NULL,
  [DescrizioneNumeroDocumento] [nvarchar](max) NULL,
.........................
.........................
  [Tipo4RiferimentoOrdineCliente] [nvarchar](max) NULL,
  [LetteraRiferimentoOrdineCliente] [nvarchar](max) NULL)

Modificato da brux88 il 25 febbraio 2017 10.07 -
Modificato da Andrea Montanari il 09 marzo 2017 18.19 - accorciato DDL in quanto ininfluente al fine del discorso se non per l'ordinalita' del numero di colonne..
1.940 messaggi dal 27 luglio 2005
Contributi
salve,
giusto per capirci un attimo, ti rendi conto che il disegno della tua tabella non rispetta le solite forme normali che e' bene valutare e comunque non e' neache molto bella da vedere, vero?

detto cio', a prescindere che io ti consiglio di ridefinire in maniera normalizzata il tuo schema, il limite superiore al numero di colonne e' pari a 1.024 per le "nonwide table" e 30.000 per le "wide table"
https://technet.microsoft.com/it-it/library/ms143432(v=sql.110).aspx
ripeto, cio' non toglie che "NON E' BELLO" fare dei mostri di questo genere

vedi comunque la risposta come definita dalla sempre bravissima Kalen in http://sqlblog.com/blogs/kalen_delaney/archive/2007/07/16/geek-city-maximum-number-of-row-overflow-columns.aspx

salutoni (e normalizza la tabella  )

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
127 messaggi dal 06 giugno 2011
Ciao, grazie per il suggerimento ;) so che non e proponibile una tabella del genere infatti sto cercando di rimodellarla. Per normalizzazione si intende evitare le duplicazioni delle proprieta ad esempio tutti i dati del cliente metterli in una tabella separata e mettere solo il riferimento id nella tabella principale giusto ?

Quindi per ogni riga di fattura avro una tabella con ogni riga del cliente corrispondente oppure metterò l'id di riferimento della tabella clienti principale quella delle anagrafcihe?

Però adottando l'ultimo caso se io faccio una fattura con cliente 1 Rossi è ha un indirizzo, poi dopo qualche mese Rossi cambia indirizzo, quindi vado nell'anagrafica di rossi e modifico l'indirizzo, id cliente rimane sempre 1, ma se poi stampo una fattura vecchia mi deve stampare con l'indirizzo vecchio, perche in quel momento aveva quell'indirizzo per questo non ho normalizzato la tabella e mi sono riportato tutto dietro cosi quella fattura rimarrà cosi a prescindere dalle modifiche che effettuerò nelle anagrafiche dei clienti, ditte,banca etc...

Il mio problema sta proprio qui... capire come poter normalizzare le tabelle se ho queste necessita...
Modificato da brux88 il 27 febbraio 2017 08.39 -
1.940 messaggi dal 27 luglio 2005
Contributi
brux88 ha scritto:
Ciao, grazie per il suggerimento ;) so che non e proponibile una tabella del genere infatti sto cercando di rimodellarla. Per normalizzazione si intende evitare le duplicazioni delle proprieta ad esempio tutti i dati del cliente metterli in una tabella separata e mettere solo il riferimento id nella tabella principale giusto ?


tendenzialmente, si :)


Quindi per ogni riga di fattura avro una tabella con ogni riga del cliente corrispondente oppure metterò l'id di riferimento della tabella clienti principale quella delle anagrafcihe?


metterai l'id... vedi "normalizzazione"


Però adottando l'ultimo caso se io faccio una fattura con cliente 1 Rossi è ha un indirizzo, poi dopo qualche mese Rossi cambia indirizzo, quindi vado nell'anagrafica di rossi e modifico l'indirizzo, id cliente rimane sempre 1, ma se poi stampo una fattura vecchia mi deve stampare con l'indirizzo vecchio, perche in quel momento aveva quell'indirizzo per questo non ho normalizzato la tabella e mi sono riportato tutto dietro cosi quella fattura rimarrà cosi a prescindere dalle modifiche che effettuerò nelle anagrafiche dei clienti, ditte,banca etc...

Il mio problema sta proprio qui... capire come poter normalizzare le tabelle se ho queste necessita...
Modificato da brux88 il 27 febbraio 2017 08.39 -


in questi casi ti serve una struttura temporale... cioe' con validita' legata ad una finestra temporale...
id: 1 - Nome: Andrea Montanari - citta': Riccione - dal: 01/01/1965 al: NULL
id: 2 - Nome: Brux88 - citta': Roma - dal: 01/01/2000 al: 31/12/2015
id: 2 - Nome: Brux88 - citta': Milano - dal: 01/01/2006 al: NULL
o simile indica che Andrea Montanari abita da sempre a Riccione, mentre Brux88 abitava a Roma dal 01/01/2000 al 31/12/2015, e quindi si e' trasferito a Milano...
(ovviamente anche questa struttura va normalizzata, quindi avrai in questo caso una tabella Indirizzo che relaziona 1 a molti con la tabella anagrafica)

la tua query per ottenere l'indirizzo, dovra' passara una data di riferimento..
quindi la query per l'acquisto di Brux88 effettuato nel 2014 referenziera' Roma, mentre l'acquisto del 2016 Milano...
si, lo so, i database temporali sono complicati e pesanti, pero' funzionano cosi'...
SQL Server 2016 ha introdotto delle novita' in questo senso, pero'...
al di la' di cio', trivialmente, si puo' fare ad esempio utilizzando anche la windowing function LEAD https://msdn.microsoft.com/it-it/library/hh213125.aspx
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.Anagrafica (
  Id int NOT NULL PRIMARY KEY,
  Nome varchar(15),
  PIVA varchar(11)
  );
CREATE TABLE dbo.Ana_Indirizzi (
  IdCliente int NOT NULL
    CONSTRAINT fk_Ana_Indir$is$Anagrafica FOREIGN KEY
      REFERENCES dbo.Anagrafica (Id),
  Citta varchar(10),
  ValidoDal date NOT NULL,
  -- NELLA REALTA' del design temporale, questo attributo ci vuole
  -- ma se e' sufficiente l'indicatore del PROSSIMO [ValidoDal]
  -- si puo' anche omettere
  ValidoAl date NULL 
  );
CREATE TABLE dbo.Fatture (
  Id int NOT NULL IDENTITY PRIMARY KEY,
  Data date NOT NULL,
  Numerazione varchar(20),
  Altro varchar(10),
  IdCliente int NOT NULL
    CONSTRAINT fk_Fatture$has$Anagrafica FOREIGN KEY
      REFERENCES dbo.Anagrafica (Id)
  );
GO
INSERT INTO dbo.Anagrafica
  VALUES (1, 'Andrea', '01000000000');
INSERT INTO dbo.Ana_Indirizzi
  VALUES (1, 'Riccione', '1965-10-30', NULL);

INSERT INTO dbo.Anagrafica
  VALUES (2, 'Brux88', '01000000001');
INSERT INTO dbo.Ana_Indirizzi
  VALUES (2, 'Roma', '1988-01-01', '2015-12-31');
INSERT INTO dbo.Ana_Indirizzi
  VALUES (2, 'Milano', '2016-01-01', NULL);

INSERT INTO dbo.Fatture
  VALUES ('2010-01-11', '12345/e', 'Altro', 1),
    ('2011-01-01', '1/a', 'Altro1', 1),
    ('2014-01-01', '1/a', 'Altro2', 1),
    ('2016-01-01', '1/a', 'Altro3', 1),
    ('2017-01-01', '1/a', 'Altro4', 1);

INSERT INTO dbo.Fatture
  VALUES ('2010-01-11', '12346/e', 'Altro10', 2),
    ('2011-01-01', '2/a', 'Altro11', 2),
    ('2014-01-01', '2/a', 'Altro12', 2),
    ('2016-01-01', '2/a', 'Altro13', 2),
    ('2017-01-01', '2/a', 'Altro14', 2);
GO
PRINT 'Elenco clienti';
SELECT *
  FROM dbo.Anagrafica a
  JOIN dbo.Ana_Indirizzi ai ON ai.IdCliente = a.Id;

PRINT 'Elenco indirizzi clienti';
WITH cteAnaInd AS (
  SELECT ai.IdCliente, ai.Citta
    , ai.ValidoDal
    , CONVERT(date, ISNULL(LEAD (ai.ValidoDal, 1) OVER (PARTITION BY ai.IdCliente ORDER BY ai.ValidoDal), GETDATE())) AS ValidoAl
    FROM dbo.Anagrafica a
      JOIN dbo.Ana_Indirizzi ai ON ai.IdCliente = a.Id
  )
  SELECT *
    FROM cteAnaInd;

PRINT 'Elenco fatture e relativi indirizzi clienti';
WITH cteAnaInd AS (
  SELECT ai.IdCliente, ai.Citta
    , ai.ValidoDal
    , CONVERT(date, ISNULL(LEAD (ai.ValidoDal, 1) OVER (PARTITION BY ai.IdCliente ORDER BY ai.ValidoDal), GETDATE())) AS ValidoAl
    FROM dbo.Anagrafica a
      JOIN dbo.Ana_Indirizzi ai ON ai.IdCliente = a.Id
  )
  SELECT f.Id, f.Data, f.Numerazione, f.Altro
    , a.Nome, a.PIVA
    , ai.Citta
    FROM dbo.Fatture f
      JOIN dbo.Anagrafica a ON a.Id = f.IdCliente
      JOIN cteAnaInd ai ON ai.IdCliente = a.Id
        AND (f.Data BETWEEN ai.ValidoDal AND ai.ValidoAl)
    ORDER by f.IdCliente, f.Data;

GO
DROP TABLE dbo.Fatture, dbo.Ana_Indirizzi, dbo.Anagrafica
--<-----------
Elenco clienti
Id          Nome            PIVA        IdCliente   Citta      ValidoDal  ValidoAl
----------- --------------- ----------- ----------- ---------- ---------- ----------
1           Andrea          01000000000 1           Riccione   1965-10-30 NULL
2           Brux88          01000000001 2           Roma       1988-01-01 2015-12-31
2           Brux88          01000000001 2           Milano     2016-01-01 NULL

Elenco indirizzi clienti
IdCliente   Citta      ValidoDal  ValidoAl
----------- ---------- ---------- ----------
1           Riccione   1965-10-30 2017-03-07
2           Roma       1988-01-01 2016-01-01
2           Milano     2016-01-01 2017-03-07

Elenco fatture e relativi indirizzi clienti
Id          Data       Numerazione          Altro      Nome            PIVA        Citta
----------- ---------- -------------------- ---------- --------------- ----------- ----------
1           2010-01-11 12345/e              Altro      Andrea          01000000000 Riccione
2           2011-01-01 1/a                  Altro1     Andrea          01000000000 Riccione
3           2014-01-01 1/a                  Altro2     Andrea          01000000000 Riccione
4           2016-01-01 1/a                  Altro3     Andrea          01000000000 Riccione
5           2017-01-01 1/a                  Altro4     Andrea          01000000000 Riccione
6           2010-01-11 12346/e              Altro10    Brux88          01000000001 Roma
7           2011-01-01 2/a                  Altro11    Brux88          01000000001 Roma
8           2014-01-01 2/a                  Altro12    Brux88          01000000001 Roma
9           2016-01-01 2/a                  Altro13    Brux88          01000000001 Roma
9           2016-01-01 2/a                  Altro13    Brux88          01000000001 Milano
10          2017-01-01 2/a                  Altro14    Brux88          01000000001 Milano


salutoni
Modificato da Andrea Montanari il 07 marzo 2017 18.53 -

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
127 messaggi dal 06 giugno 2011
grazie per la risposta e sopratutto per l'esempio, adesso approfondirò sui db temporali partendo dal tuo esempio, vedendo la mia tabella ci saranno molti join, perche oltre ai dati clienti, dovrò normalizzare i dati ditta,dati pagamento,dati agente,dati fornitori etc.. in questo caso è sempre consigliato normalizzare il db? cioe ogni qualvolta dovro prendere la fattura a video dovro fare un bel po di join per poter visualizzare i dati giusto?

infine considerando l'esempio della modifica dell'anagrafica del cliente, ogni qual volta apporto una modifica che sia nella descrizione o nell'indirizzo, oppure nelle note mi dovro creare un nuovo cliente sempre con la data di validità dal?
1.940 messaggi dal 27 luglio 2005
Contributi
salve,
brux88 ha scritto:
grazie per la risposta e sopratutto per l'esempio, adesso approfondirò sui db temporali partendo dal tuo esempio, ...

se ti vuoi far del male :), interessantissima bibliografia la trovi a partire da https://www2.cs.arizona.edu/people/rts/ che ti portera' a http://timecenter.cs.aau.dk/pub.htm ... interessantissimi anche se probabilmente overkill :)

vedendo la mia tabella ci saranno molti join, perche oltre ai dati clienti, dovrò normalizzare i dati ditta,dati pagamento,dati agente,dati fornitori etc.. in questo caso è sempre consigliato normalizzare il db?


tendenzialmente si, perche' il fine ultimo e' comunque avere una base dati "valida", dove i dati abbiano valore...
cioe ogni qualvolta dovro prendere la fattura a video dovro fare un bel po di join per poter visualizzare i dati giusto?


eh si... :)

infine considerando l'esempio della modifica dell'anagrafica del cliente, ogni qual volta apporto una modifica che sia nella descrizione o nell'indirizzo, oppure nelle note mi dovro creare un nuovo cliente sempre con la data di validità dal?

qui devi valutare tu il senso della modifica, e la tua analisi dovrebbe cercare di "minimizzare" i fenomeni di chaining... nel senso, cambiando l'indirizzo di spedizione, ovviamente dovrai inserire una nuova riga che identifichi le nuove spedizioni a partire dal XX al nuovo indirizzo... per il telefono, uguale...
mentre forse alcuni attributi potrebbero essere ininfluenti nella tua analisi per la specifica di una nuova riga...
saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
127 messaggi dal 06 giugno 2011
Grazie chiarissimo , adesso approfondisco e cerco di fare un attenta analisi

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.