193 messaggi dal 05 settembre 2001
Ho creato una stored procedure di questo tipo:
CREATE PROCEDURE [dbo].[updinv]

AS 

DECLARE 
    @get_id     AS CURSOR,
    @itype      AS SYSNAME,
    @iupgr      AS FLOAT,
    @igame      AS INT
    
SET @get_id = CURSOR FOR SELECT itype, iupgr, igame  FROM investimenti /*WHERE pgameon = 1*/
SET @itype  = ''
SET @iupgr  = ''
SET @igame  = ''


OPEN @get_id

FETCH NEXT FROM @get_id INTO @itype, @iupgr, @igame

WHILE @@FETCH_STATUS = 0

BEGIN

    SET @itype      = 'p' + @itype
    
    UPDATE popolazione SET @itype = @itype + @iupgr
    WHERE pid = @igame
   

    
    FETCH NEXT FROM @get_id INTO @itype, @iupgr, @igame
END 


CLOSE @get_id
DEALLOCATE @get_id


Lo scopo è di fare un ciclo all'interno di una tabella, prendere il valore di un campo char (che coincide con il nome del campo di un altra tabella che andrò ad aggiornare), ed un valore integer (che sarà il valore dell'aggiornamento) e aggiornare una seconda tabella...con un esempio forse si capisce meglio. Questo è il risultato finale:

Tabella1:

CampoUpd      Valore
--------------------
Campo1         0.01
Campo2         0.05
Campo3         0.08


Tabella2:

Campo1      Campo2      Campo3
-------------------------------
0.01        0.05          0.08    


Solo che la SP di prima non funziona perchè considera la variabile @itype come char e non come recordset. Quindi mi restituisce questo errore:


Error: Si è verificato un errore durante la conversione del tipo di dati da nvarchar a float

Qualche idea?
Modificato da s_dimaio il 21 aprile 2005 20.02 -
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
s_dimaio wrote:
Error: Si è verificato un errore durante la conversione del tipo di
dati da nvarchar a float
Ci sono una serie di errori e non uno soltanto...
Partiamo da quello che ti viene indicato da questo messaggio di errore... per concatenare un valore numerico con un valore stringa devi fare un CAST esplicito. Se vuoi ottenere la stringa 'Luca1' come concatenazione di 'Luca' e 1 non puoi scrivere

SELECT 'Luca' + 1

che ti da un errore analogo a quello che hai riportato ma dovrai scrivere

SELECT 'Luca' + CAST(1 AS VARCHAR(5))

oppure in alternativa alla funzione CAST puoi utilizzare la CONVERT

SELECT 'Luca' + CONVERT(VARCHAR(5), 1)

In secondo luogo l'utilizzo del datatype FLOAT può darti risultati inattesi (è un datatype approssimato) in quanto sarebbe più idoneo utilizzare un datatype esatto come DECIMAL (x, y). Ti invito a fare questa prova. Crea una tabella definita come

CREATE TABLE dbo.MyTable
(
Val FLOAT( NOT NULL
)

quindi inserisci i seguenti record

INSERT dbo.MyTable VALUES (300000.77)
INSERT dbo.MyTable VALUES (300000.79)
INSERT dbo.MyTable VALUES (400000.11)
INSERT dbo.MyTable VALUES (400000.15)
INSERT dbo.MyTable VALUES (500000.45)
INSERT dbo.MyTable VALUES (500000.42)
INSERT dbo.MyTable VALUES (600000.36)
INSERT dbo.MyTable VALUES (600000.4)

e a questo punto interroga la tabella

SELECT *
FROM dbo.MyTable...cosa noti? :-)

Poi nel cursore (che già sarebbe da evitare) esegui il comando UPDATE utilizzando nella clausola SET una variabile al posto del nome di un campo. Non si può.

Infine dall'esempio che hai fornito hai detto qual'è il risultato che vuoi ottenere ma non hai indicato il punto di partenza. Manda un breve script per ricreare la struttura della tabella di esempio, inserire alcune righe di prova (in maniera simile a come ho fatto per dimostrarti l'inopportunità di utilizzare un float) ed il risultato che vuoi ottenere. Insomma... aiutaci ad aiutarti... ;-)

Bye
193 messaggi dal 05 settembre 2001

l.bianchi ha scritto:


Poi nel cursore (che già sarebbe da evitare) esegui il comando UPDATE utilizzando nella clausola SET una variabile al posto del nome di un campo. Non si può.



Il mio problema è esattamento questo: non so quale campo della "Tabella 2" devo aggiornare, dipende da quanto scritto nella "Tabella 1". Le due tabelle hanno una struttura del tipo:

Tabella1:

CampoUpd......Valore
-------------------------
Campo1..........0.01
Campo2..........0.05
Campo3..........0.08


Tabella2:

Campo1........Campo2........Campo3
-----------------------------------
0.01
..........................0.05
.............................................0.08


Quindi devo passare alla query di update un campo variabile

UPDATE Tabella2 SET ---dipende dal campoUpd della Tabella1--- = ---dipende dal Valore della Tabella1---

Spero di essere stato più chiaro.

Ciao e grazie
Modificato da s_dimaio il 22 aprile 2005 14.31 -
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
s_dimaio wrote:
Il mio problema è esattamento questo: non so quale campo della
"Tabella 2" devo aggiornare, dipende da quanto scritto nella "Tabella
1". Le due tabelle hanno una struttura del tipo:

Tabella1:

CampoUpd......Valore
-------------------------
Campo1..........0.01
Campo2..........0.05
Campo3..........0.08...questa è una struttura plausibile...
Tabella2:

Campo1........Campo2........Campo3
-----------------------------------
0.01
.........................0.05
............................................0.08...ma questa ho il forte sospetto che non sia esattamente così. Vuoi farmi
credere che la tabella contiene i record

0.01 NULL NULL
NULL 0.05 NULL
NULL NULL 0.08

???
Se le cose stanno così prima di tutto prendi a sassate chi ha disegnato una struttura simile...
Partiamo quindi con il definire la struttura e i dati così come li hai riportati

========================
CREATE TABLE dbo.Tabella1
(
Campo varchar(10) NOT NULL,
Valore decimal (9, 2) NOT NULL
)
GO

CREATE TABLE dbo.Tabella2
(
Campo1 decimal(9, 2) NULL,
Campo2 decimal(9, 2) NULL,
Campo3 decimal(9, 2) NULL
)
GO

INSERT dbo.Tabella1 VALUES('Campo1', 0.01)
INSERT dbo.Tabella1 VALUES('Campo2', 0.05)
INSERT dbo.Tabella1 VALUES('Campo3', 0.0

INSERT dbo.Tabella2 VALUES(0.01, NULL, NULL)
INSERT dbo.Tabella2 VALUES(NULL, 0.05, NULL)
INSERT dbo.Tabella2 VALUES(NULL, NULL, 0.0
GO
========================

(questo intendevo nel mio precedente post quando ti chiedevo di postare uno script per riprodurre lo scenario). A questo punto come prima cosa mettiamo a posto la "tabella" che contiene i dati che devono essere presi in considerazione per procedere all'aggiornamento. Per semplicità mi definisco una vista

========================
CREATE VIEW dbo.vw_Tabella2
AS
SELECT MAX(ISNULL(Campo1, 0)) Campo1,
MAX(ISNULL(Campo2, 0)) Campo2,
MAX(ISNULL(Campo3, 0)) Campo3
FROM dbo.Tabella2
========================

a questo punto quindi aggiorno Tabella1 sulla base del contenuto della vista. Quindi

========================
UPDATE A
SET Valore =
CASE
WHEN Campo = 'Campo1' THEN B.Campo1
WHEN Campo = 'Campo2' THEN B.Campo2
WHEN Campo = 'Campo3' THEN B.Campo3
END
========================
Quindi devo passare alla query di update un campo variabile...che ti ripeto che non puoi fare...
Spero di essere stato più chiaro.
Si, e come vedi l'alternativa all'uso del cursore (anche quando il cursore non avrebbe funzionato per il motivo di cui sopra) esiste. Ti consiglio di fare in modo che la struttura dati assuma una forma meno "estroversa" altrimenti i problemi di oggi te li ritroverai amplificati in breve tempo...
Ciao e grazie
Bye
193 messaggi dal 05 settembre 2001
Nella Tabella 2 non esistono campi nulli, era solo un esempio. Per non scrivere molto alla fine sono stato troppo stringato.

Per capirci faccio una situazione più completa:
CREATE TABLE dbo.Tabella1
(
Campo varchar(10) NOT NULL,
Valore decimal (9, 2) NOT NULL,
Id1 Int NOT NULL
)
GO

CREATE TABLE dbo.Tabella2
(
Id2 Int NOT NULL,
Campo1 decimal(9, 2) NOT NULL,
Campo2 decimal(9, 2) NOT NULL,
Campo3 decimal(9, 2) NOT NULL
)
GO

INSERT dbo.Tabella1 VALUES('Campo1', 0.01, 1)
INSERT dbo.Tabella1 VALUES('Campo2', 0.05, 2)
INSERT dbo.Tabella1 VALUES('Campo3', 0.03, 3)

INSERT dbo.Tabella2 VALUES(1, 0.11, 0.03, 0.07)
INSERT dbo.Tabella2 VALUES(2, 0.12, 0.15, 0.18)
INSERT dbo.Tabella2 VALUES(3, 0.25, 0.11, 0.30)
GO


Guarda la tabella 2: quella che vedi è la situazione iniziale.

A questo punto la mia SP deve fare il ciclo di tutti i campi della "Tabella 1" ed aggiornare la "Tabella 2" in modo da ottenere questo risultato (le differenze sono in neretto):

INSERT dbo.Tabella2 VALUES(1, <b>0.01</b>, 0.03, 0.07)
INSERT dbo.Tabella2 VALUES(2, 0.12, <b>0.05</b>, 0.15)
INSERT dbo.Tabella2 VALUES(2, 0.25, 0.11, <b>0.03</b>)


Quella che deve essere aggiornata è quindi la "Tabella 2".
La riga della "Tabella 2" da aggiornare è quella in corrispondenza dello stesso Id.
Il campo della "Tabella 2" da aggiornare è quello indicato nella colonna "Campo" della "Tabella 1".
Il valore che il campo di cui sopra della "Tabella 2" deve prendere è quello indicato nella colonna "Valore" della "Tabella 1".

Ho visto il tuo suggerimento ma, se non l'ho male interpretato, mi sembra non faccia al caso mio. Puoi provare a spiegarmi meglio i passaggi?

Ciao
Modificato da s_dimaio il 22 aprile 2005 22.59 -
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
s_dimaio wrote:
Nella Tabella 2 non esistono campi nulli, era solo un esempio. Per non
scrivere molto alla fine sono stato troppo stringato.

Per capirci faccio una situazione più completa:...ottimo!
A questo punto la mia SP deve fare il ciclo di tutti i campi della
"Tabella 1" ed aggiornare la "Tabella 2" in modo da ottenere questo
risultato (le differenze sono in neretto):...aridagli con il ciclo... :-)
Questa istruzione esegue l'attività che hai indicato (questa volta senza ombra di dubbio visto l'ottimo esempio che hai fornito)

============================
UPDATE B
SET Campo1 =
CASE A.Campo
WHEN 'Campo1' THEN A.Valore
ELSE B.Campo1
END,
Campo2 =
CASE A.Campo
WHEN 'Campo2' THEN A.Valore
ELSE B.Campo2
END,
Campo3 =
CASE A.Campo
WHEN 'Campo3' THEN A.Valore
ELSE B.Campo3
END
FROM dbo.Tabella1 A INNER JOIN dbo.Tabella2 B
ON A.Id1 = B.Id2

============================

e, cosa più importante, senza utilizzare un cursore che come noto ammazza le prestazioni oltre a non essere possibile secondo le tue intenzioni in quanto il nome di un campo, di una tabella e di qualunque altro oggetto di SQL Server non può essere rappresentato da una variabile
Ciao
Modificato da s_dimaio il 22 aprile 2005 22.59 -
Bye
193 messaggi dal 05 settembre 2001
Ok, perfetto. Così funziona...però ti complico un po' le cose aggiungendo un altro campo alla "Tabella1"

CREATE TABLE dbo.Tabella1 
( 
Campo varchar(10) NOT NULL, 
Valore decimal (9, 2) NOT NULL, 
Id1 Int NOT NULL 
<b>Flag Bit NOT NULL</b>
) 
GO 

CREATE TABLE dbo.Tabella2 
( 
Id2 Int NOT NULL, 
Campo1 decimal(9, 2) NOT NULL, 
Campo2 decimal(9, 2) NOT NULL, 
Campo3 decimal(9, 2) NOT NULL 
) 
GO 

INSERT dbo.Tabella1 VALUES('Campo1', 0.01, 1, 0) 
INSERT dbo.Tabella1 VALUES('Campo2', 0.05, 2, 1) 
INSERT dbo.Tabella1 VALUES('Campo3', 0.03, 3, 1) 

INSERT dbo.Tabella2 VALUES(1, 0.11, 0.03, 0.07) 
INSERT dbo.Tabella2 VALUES(2, 0.12, 0.15, 0.18) 
INSERT dbo.Tabella2 VALUES(3, 0.25, 0.11, 0.30) 
GO 




L'obiettivo è aggiornare le righe della "Tabella 2" solo in corrispondenza del Flag 1 nella "Tabella 1".
La mia query diventa:

UPDATE B
SET Campo1 =
CASE A.Campo
WHEN 'Campo1' THEN A.Valore
ELSE B.Campo1
END,
Campo2 =
CASE A.Campo
WHEN 'Campo2' THEN A.Valore
ELSE B.Campo2
END,
Campo3 =
CASE A.Campo
WHEN 'Campo3' THEN A.Valore
ELSE B.Campo3
END
FROM dbo.Tabella1 A INNER JOIN dbo.Tabella2 B
ON A.Id1 = B.Id2

<b>WHERE   ...    A.Flag = 1</b>


I puntini sono messi al posto di tutta una serie di condizioni che devono essere verificate. Da ultimo ci deve essere anche la condizione che A.Flag sai pari a 1.

Fino a qui tutto bene. Solo che una volta aggiornata la riga della "Tabella 2" devo settare il campo "Flag" della "Tabella 1" a 0 di modo da non fare più l'aggiornamento al giro successivo.

Potrei tranquillamente inserire nella mia SP un secondo UPDATE che setta a 0 il Flag per le stesse condizioni che soddisfacevano la prima query.

Esiste però un'altra strada, magari migliore?

Ciao
Modificato da s_dimaio il 24 aprile 2005 12.33 -
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
s_dimaio wrote:
Esiste però un'altra strada, magari migliore?...aggiungi nella clausola SET l'aggiornamento di un secondo campo...

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.