Wie rufe ich mehrere Spalten zur Verwendung in einer Cursorschleife ab?

87

Wenn ich versuche, das folgende SQL-Snippet in einer Cursorschleife auszuführen,

set @cmd = N'exec sp_rename ' + @test + N',' +
           RIGHT(@test,LEN(@test)-3) + '_Pct' + N',''COLUMN'''

Ich erhalte die folgende Nachricht:

Nachricht 15248, Ebene 11, Status 1, Prozedur sp_rename, Zeile 213
Entweder ist der Parameter @objnamemehrdeutig oder der beanspruchte @objtype(COLUMN) ist falsch.

Was ist falsch und wie behebe ich es? Ich habe versucht, den Spaltennamen in Klammern zu setzen []und doppelte Anführungszeichen zu setzen, ""wie einige der vorgeschlagenen Suchergebnisse.

Bearbeiten 1 -

Hier ist das gesamte Skript. Wie übergebe ich den Tabellennamen an die Umbenennung sp? Ich bin mir nicht sicher, wie ich das machen soll, da sich die Spaltennamen in einer von vielen Tabellen befinden.

BEGIN TRANSACTION

declare @cnt int
declare @test nvarchar(128)
declare @cmd nvarchar(500) 
declare Tests cursor for
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE 'pct%' AND TABLE_NAME LIKE 'TestData%'

open Tests
fetch next from Tests into @test
while @@fetch_status = 0
BEGIN
  set @cmd = N'exec sp_rename ' + @test + N',' + RIGHT(@test,LEN(@test)-3) + '_Pct' + N', column' 

  print @cmd

  EXEC sp_executeSQL @cmd

  fetch next from Tests into @test
END

close Tests 
deallocate Tests


ROLLBACK TRANSACTION
--COMMIT TRANSACTION

Bearbeiten 2 - Das Skript dient zum Umbenennen von Spalten, deren Namen mit einem Muster übereinstimmen, in diesem Fall mit dem Präfix "pct". Die Spalten kommen in verschiedenen Tabellen in der Datenbank vor. Allen Tabellennamen wird "TestData" vorangestellt.

Joe
quelle
1
Diese Zeile verkettet eine Zeichenfolge. Warum druckst du es nicht aus, damit du sehen kannst, was der Inhalt der Zeichenfolge ist?
Preet Sangha
@testhat die Form von table.columnoderschema.table.column , nicht wahr?
GSerg
Wenn @test einen qualifizierten Namen enthält, muss er in Apostrophen stehen. Wenn dieselbe Annahme zutrifft, entfernt right () die ersten drei Zeichen im Tabellennamen. in Sie wollten die letzten Zeichen des Spaltennamens ersetzen, dies wäre LEFT. Könnten Sie bitte das Skript ein wenig erweitern, indem Sie set @test = ... hinzufügen?
Nikola Markovinović
Ihr Code hat mir tatsächlich geholfen, mein Problem zu lösen - danke dafür!
Neville

Antworten:

155

Hier ist eine leicht modifizierte Version. Änderungen werden als Codekommentar vermerkt.

BEGIN TRANSACTION

declare @cnt int
declare @test nvarchar(128)
-- variable to hold table name
declare @tableName nvarchar(255)
declare @cmd nvarchar(500) 
-- local means the cursor name is private to this code
-- fast_forward enables some speed optimizations
declare Tests cursor local fast_forward for
 SELECT COLUMN_NAME, TABLE_NAME
   FROM INFORMATION_SCHEMA.COLUMNS 
  WHERE COLUMN_NAME LIKE 'pct%' 
    AND TABLE_NAME LIKE 'TestData%'

open Tests
-- Instead of fetching twice, I rather set up no-exit loop
while 1 = 1
BEGIN
  -- And then fetch
  fetch next from Tests into @test, @tableName
  -- And then, if no row is fetched, exit the loop
  if @@fetch_status <> 0
  begin
     break
  end
  -- Quotename is needed if you ever use special characters
  -- in table/column names. Spaces, reserved words etc.
  -- Other changes add apostrophes at right places.
  set @cmd = N'exec sp_rename ''' 
           + quotename(@tableName) 
           + '.' 
           + quotename(@test) 
           + N''',''' 
           + RIGHT(@test,LEN(@test)-3) 
           + '_Pct''' 
           + N', ''column''' 

  print @cmd

  EXEC sp_executeSQL @cmd
END

close Tests 
deallocate Tests

ROLLBACK TRANSACTION
--COMMIT TRANSACTION
Nikola Markovinović
quelle
2
Eine meiner Lieblingsantworten in SO.
Rubens Mariuzzo
@ RubensMariuzzo Danke, Sie sind zu großzügig :-)
Nikola Markovinović
60
TLDR; FETCH NEXT FROM db_cursor INTO @var1, @ var2
Don Rolling
7
TLDR wird üblicherweise verwendet, um eine kurze Version einer längeren Information anzuzeigen. Es steht für Too Long Didn't Read. Ich habe vorgeschlagen, dass es eine kürzere Version der Antwort gibt, die Sie gegeben haben, und ich habe sie gegeben.
Don Rolling
1
Nice Touch, nicht zweimal holen. :)
Gewinner_joiner