Saving changes is not permitted en SQL Server

Trabajando en una instalación limpia de SQL Server Management Studio, si intentas modificar la estructura de una tabla, puedes encontrarte este error al intentarla guardar:

Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the option Prevent saving changes that require the table to be re-created.

Si oprimes Cancel, no se guarda ningún cambio.

La solución es muy sencilla, abre Microsoft SQL Server Management Studio y haz clic en el menú Tools, y luego en Options.

Después en la columna izquierda selecciona Designers y desmarca la casilla Prevent saving changes that require table re-creation.

Y listo, ahora podrás modificar tu tabla y guardar los cambios.

User, group, or role already exists in the current database.

Seguramente te ha pasado que al migrar una base de datos de SQL Server de un servidor a otro, haces tu backup usando Microsoft SQL Server Management Studio, transfieres el archivo, y haces el restore en el nuevo servidor. Todo parece perfecto, pero cuando vas a crear tu usuario obtienes el siguiente error:

User, group, or role '' already exists in the current database. (Microsoft SQL Server, Error: 15023)

Entonces expandes tu base de datos, vas al nodo Security -> Users, buscas el usuario, y lo intentas borrar, pero entonces aparece otro error:

Drop failed for User ''. (Microsoft.SqlServer.Smo). The database principal owns a database role and cannot be dropped. (Microsoft SQL Server, Error: 15421)

En este punto te das cuenta de que el usuario está “huérfano” (orphaned), y una solución para darle la vuelta al problema es crear un nuevo usuario con otro nombre, asignarlo a la base de datos, y modificar el nombre del usuario en el Connection String de tu aplicación.

Pero existe una manera de solucionar las cosas correcta y fácilmente.

Abre una ventana de query en tu base de datos y teclea lo siguiente para ver los usuarios huérfanos:

EXEC sp_change_users_login 'Report'

Si ves a tu usuario ahí significa que efectivamente está huérfano y para deshuerfanizarlo 😉 teclea lo siguiente:

EXEC sp_change_users_login 'Auto_Fix', 'user'

Modificando user por el nombre de tu usuario.

Y listo, asunto totalmente solucionado, no tienes que crear nuevos usuarios ni modificar las Connection Strings de tus aplicaciones.

Por último, si quieres crear un nuevo usuario para esta base de datos, usa:

EXEC sp_change_users_login 'Auto_Fix', 'user', 'login', 'password'

Palabras reservadas de SQL Server 2005

Las siguientes palabras son palabras reservadas (Reserved Keywords) para SQL Server 2005. Si vas a crear una tabla, columna, o algún otro elemento en tu base de datos, trata de no utilizar alguna de las siguientes palabras. Si por alguna razón lo haces, deberás utilizar los delimitadores “[” y “]” en tus sentencias.

Por ejemplo, si creas una tabla llamada Abort utilízala como sigue:

SELECT * From [Abort]

De lo contrario, generarás un error.

Las palabras reservadas son:

A
ABORT
ABS
ABSOLUTE
ACCESS
ACOS
ACQUIRE
ACTION
ACTIVATE
ADA
ADD
ADDFORM
ADMIN
AFTER
AGGREGATE
ALIAS
ALL
ALLOCATE
ALTER
AN
ANALYZE
AND
ANY
APPEND
ARCHIVE
ARCHIVELOG
ARE
ARRAY
ARRAYLEN
AS
ASC
ASCII
ASIN
ASSERTION
AT
ATAN
AUDIT
AUTHORIZATION
AVG
AVGU
BACKUP
BECOME
BEFORE
BEGIN
BETWEEN
BIGINT
BINARY
BIND
BINDING
BIT
BLOB
BLOCK
BODY
BOOLEAN
BOTH
BREADTH
BREAK
BREAKDISPLAY
BROWSE
BUFFERPOOL
BULK
BY
BYREF
CACHE
CALL
CALLPROC
CANCEL
CAPTURE
CASCADE
CASCADED
CASE
CAST
CATALOG
CCSID
CEILING
CHANGE
CHAR
CHARACTER
CHARTOROWID
CHECK
CLASS
CLOB
CHECKPOINT
CHR
CLEANUP
CLEAR
CLEARROW
CLOSE
CLUSTER
CLUSTERED
COALESCE
COBOL
COLGROUP
COLLATE
COLLATION
COLLECTION
COLUMN
COMMAND
COMMENT
COMMIT
COMPLETION
COMMITTED
COMPILE
COMPLEX
COMPRESS
COMPUTE
CONCAT
CONFIRM
CONNECT
CONNECTION
CONSTRAINT
CONSTRAINTS
CONSTRUCTOR
CONTAINS
CONTAINSTABLE
CONTENTS
CONTINUE
CONTROLFILE
CONTROLROW
CONVERT
COPY
CORRESPONDING
COS
COUNT
COUNTU
CREATE
CROSS
CUBE
CURRENT
CURRENT_DATE
CURRENT_PATH
CURRENT_ROLE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_USER
CURSOR
CVAR
CYCLE
DATA
DATABASE
DATAFILE
DATAHANDLER
DATAPAGES
DATE
DAY
DAYOFMONTH
DAYOFWEEK
DAYOFYEAR
DAYS
DBA
DBCC
DBSPACE
DEALLOCATE
DEC
DECIMAL
DECLARATION
DECLARE
DECODE
DEFAULT
DEFERRABLE
DEFERRED
DEFINE
DEFINITION
DEGREES
DELETE
DEPTH
DEREF
DELETEROW
DENY
DESC
DESCRIBE
DESCRIPTOR
DESTROY
DHTYPE
DESTRUCTOR
DETERMINISTIC
DICTIONARY
DIAGNOSTICS
DIRECT
DISABLE
DISCONNECT
DISK
DISMOUNT
DISPLAY
DISTINCT
DISTRIBUTE
DISTRIBUTED
DO
DOMAIN
DOUBLE
DOWN
DROP
DUMMY
DUMP
DYNAMIC
EACH
EDITPROC
ELSE
ELSEIF
ENABLE
END
ENDDATA
ENDDISPLAY
ENDEXEC
END-EXEC
ENDFORMS
ENDIF
ENDLOOP
EQUALS
ENDSELECT
ENDWHILE
ERASE
ERRLVL
ERROREXIT
ESCAPE
EVENTS
EVERY
EXCEPT
EXCEPTION
EXCEPTIONS
EXCLUDE
EXCLUDING
EXCLUSIVE
EXEC
EXECUTE
EXISTS
EXIT
EXP
EXPLAIN
EXPLICIT
EXTENT
EXTERNAL
EXTERNALLY
EXTRACT
FALSE
FETCH
FIELD
FIELDPROC
FILE
FILLFACTOR
FINALIZE
FINALIZE
FIRST
FLOAT
FLOOR
FLOPPY
FLUSH
FOR
FORCE
FORMDATA
FORMINIT
FORMS
FORTRAN
FOREIGN
FOUND
FREELIST
FREELISTS
FREETEXT
FREETEXTTABLE
FROM
FREE
FULL
FUNCTION
GENERAL
GET
GETCURRENTCONNECTION
GETFORM
GETOPER
GETROW
GLOBAL
GO
GOTO
GRANT
GRANTED
GRAPHIC
GREATEST
GROUP
GROUPING
GROUPS
HASH
HAVING
HOST
HELP
HELPFILE
HOLDLOCK
HOUR
HOURS
IDENTIFIED
IDENTITY
IGNORE
IDENTITYCOL
IF
IFNULL
IIMESSAGE
IIPRINTF
IMMEDIATE
IMPORT
IN
INCLUDE
INCLUDING
INCREMENT
INDEX
INDEXPAGES
INDICATOR
INITCAP
INITIAL
INITIALIZE
INITIALLY
INITRANS
INITTABLE
INNER
INOUT
INPUT
INSENSITIVE
INSERT
INSERTROW
INSTANCE
INSTR
INT
INTEGER
INTEGRITY
INTERFACE
INTERSECT
INTERVAL
INTO
IS
ISOLATION
ITERATE
JOIN
KEY
KILL
LABEL
LANGUAGE
LARGE
LAST
LATERAL
LAYER
LEADING
LEAST
LEFT
LESS
LENGTH
LEVEL
LIKE
LIMIT
LINENO
LINK
LIST
LISTS
LOAD
LOADTABLE
LOCAL
LOCALTIME
LOCALTIMESTAMP
LOCATOR
LOCATE
LOCK
LOCKSIZE
LOG
LOGFILE
LONG
LONGINT
LOWER
LPAD
LTRIM
LVARBINARY
LVARCHAR
MAIN
MANAGE
MANUAL
MAP
MATCH
MAX
MAXDATAFILES
MAXEXTENTS
MAXINSTANCES
MAXLOGFILES
MAXLOGHISTORY
MAXLOGMEMBERS
MAXTRANS
MAXVALUE
MENUITEM
MESSAGE
MICROSECOND
MICROSECONDS
MIN
MINEXTENTS
MINUS
MINUTE
MODIFIES
MINUTES
MINVALUE
MIRROREXIT
MOD
MODE
MODIFY
MODULE
MONEY
MONTH
MONTHS
MOUNT
MOVE
NAMED
NAMES
NATIONAL
NATURAL
NCHAR
NCLOB
NEW
NEXT
NHEADER
NO
NOARCHIVELOG
NOAUDIT
NOCACHE
NOCHECK
NOCOMPRESS
NOCYCLE
NOECHO
NOMAXVALUE
NOMINVALUE
NONCLUSTERED
NONE
NOORDER
NORESETLOGS
NORMAL
NOSORT
NOT
NOTFOUND
NOTRIM
NOWAIT
NULL
NULLIF
NULLVALUE
NUMBER
NUMERIC
OBJECT
NUMPARTS
NVL
OBID
ODBCINFO
OF
OFF
OFFLINE
OFFSETS
OLD
ON
ONCE
ONLINE
ONLY
OPEN
OPERATION
OPENDATASOURCE
OPENQUERY
OPENROWSET
OPTIMAL
OPTIMIZE
OPTION
OR
ORDER
ORDINALITY
OUT
OUTER
OUTPUT
OVER
OVERLAPS
OWN
PACKAGE
PAD
PARAMETER
PARAMETERS
PAGE
PAGES
PARALLEL
PART
PARTIAL
PATH
POSTFIX
PASCAL
PCTFREE
PCTINCREASE
PCTINDEX
PCTUSED
PERCENT
PERM
PERMANENT
PERMIT
PI
PIPE
PLAN
PLI
POSITION
POWER
PRECISION
PREFIX
PREORDER
PREPARE
PRESERVE
PRIMARY
PRINT
PRINTSCREEN
PRIOR
PRIQTY
PRIVATE
PRIVILEGES
PROC
PROCEDURE
PROCESSEXIT
PROFILE
PROGRAM
PROMPT
PUBLIC
PUTFORM
PUTOPER
PUTROW
QUALIFICATION
QUARTER
QUOTA
RADIANS
RAISE
RAISERROR
RAND
RANGE
RAW
READ
READS
READTEXT
REAL
RECURSIVE
REF
RECONFIGURE
RECORD
RECOVER
REDISPLAY
REFERENCES
REFERENCING
RELATIVE
REGISTER
RELEASE
RELOCATE
REMOVE
RENAME
REPEAT
REPEATABLE
REPEATED
REPLACE
REPLICATE
REPLICATION
RESET
RESETLOGS
RESOURCE
RESTORE
RESTRICT
RESULT
RESTRICTED
RESUME
RETRIEVE
RETURN
RETURNS
REUSE
REVOKE
RIGHT
ROLE
ROLES
ROLLBACK
ROLLUP
ROUTINE
ROW
ROWS
ROWCOUNT
ROWGUIDCOL
ROWID
ROWIDTOCHAR
ROWLABEL
ROWNUM
ROWS
RPAD
RRN
RTRIM
RULE
RUN
RUNTIMESTATISTICS
SAVE
SAVEPOINT
SCHEDULE
SCHEMA
SCN
SCREEN
SCROLL
SCOPE
SEARCH
SCROLLDOWN
SCROLLUP
SECOND
SECONDS
SECQTY
SECTION
SEGMENT
SELECT
SEQUENCE
SERIALIZABLE
SERVICE
SESSION
SESSION_USER
SET
SETS
SETUSER
SIN
SIMPLE
SIGN
SHUTDOWN
SHORT
SHARE
SHARED
SETUSER
SIZE
SLEEP
SMALLINT
SNAPSHOT
SOME
SORT
SOUNDEX
SPACE
SPECIFIC
SPECIFICTYPE
SQL
SQLEXCEPTION
SQLBUF
SQLCA
SQLCODE
SQLERROR
SQLSTATE
SQLWARNING
SQRT
START
STATE
STATEMENT
STATIC
STRUCTURE
STATISTICS
STOGROUP
STOP
STORAGE
STORPOOL
SUBMENU
SUBPAGES
SUBSTR
SUBSTRING
SUCCESSFUL
SUFFIX
SUM
SYSTEM_USER
SUMU
SWITCH
SYNONYM
SYSCAT
SYSDATE
SYSFUN
SYSIBM
SYSSTAT
SYSTEM
SYSTIME
SYSTIMESTAMP
TABLE
TABLEDATA
TABLES
TABLESPACE
TAN
TAPE
TEMP
TEMPORARY
TERMINATE
THAN
TEXTSIZE
THEN
THREAD
TIME
TIMEOUT
TIMESTAMP
TIMEZONE_HOUR
TIMEZONE_MINUTE
TINYINT
TO
TOP
TPE
TRACING
TRAILING
TRAN
TRANSACTION
TRANSLATE
TRANSLATION
TREAT
TRIGGER
TRIGGERS
TRIM
TRUE
TRUNCATE
TSEQUAL
TYPE
UID
UNCOMMITTED
UNDER
UNION
UNIQUE
UNKNOWN
UNNEST
UNLIMITED
UNLOADTABLE
UNSIGNED
UNTIL
UP
UPDATE
UPDATETEXT
UPPER
USAGE
USE
USER
USING
UUID
VALIDATE
VALIDPROC
VALIDROW
VALUE
VALUES
VARBINARY
VARCHAR
VARIABLE
VARIABLES
VARYING
VCAT
VERSION
VIEW
VOLUMES
WAITFOR
WEEK
WHEN
WHENEVER
WHERE
WHILE
WITH
WITHOUT
WORK
WRITE
WRITETEXT
YEAR
YEARS
ZONE

Cómo restablecer el valor de una columna Identity en SQL Server

Las columnas marcadas como Identity en SQL Server van incrementando de acuerdo a una seed o semilla. Normalmente empiezan en 1 y van incrementando de 1 en 1. Si has insertado, por ejemplo, 20 registros, el valor del Identity será 21. Si eliminas todos los registros e insertas uno nuevo, verás que en vez de empezar nuevamente del 1, continuará en el 21.

Hay ocasiones en las que necesitamos que el Identity vuelva a empezar en 1. Para esto, se necesita restablecer la semilla, lo cual se llama reseed.

Todos los procedimientos siguientes utilizan el comando DBCC y se hacen mediante tu editor de consultas (queries) favorito, por ejemplo Microsoft SQL Server Management Studio.

Para verificar el valor de la semilla

DBCC checkident ('NombreDeTabla')

Resultado:

Checking identity information: current identity value '20', current column value '20'.

Para reparar la semilla
Si por alguna extraña razón la semilla se corrompe, puedes repararla con el siguiente comando, el cual modificará el valor de la semilla al valor máximo que se encuentre almacenado en la columna Identity.

DBCC checkident ('NombreDeTabla', reseed)

Resultado:

Checking identity information: current identity value '20', current column value '20'.

Restablecer la semilla
Como comentaba al principio, si borraste todos los registros y necesitas reiniciar la semilla en 1, entonces emite el siguiente comando:

DBCC checkident ('NombreDeTabla', reseed, 1)

Resultado:

Checking identity information: current identity value '20', current column value '1'.

Listo, el registro siguiente que insertes tendrá un valor Identity de 1. Puedes modificar el valor 1 a cualquier otro valor que necesites en el ejemplo del último comando.

Cómo insertar valores en columnas Identity

Si intentas insertar (mediante algún software de sincronización de bases de datos o cualquier otro método) valores explí­citos en columnas marcadas como Identity, obtendrás este error:

Cannot insert explicit value for identity column in table 'MiTabla' when IDENTITY_INSERT is set to OFF

Para poder insertar valores especí­ficos en estas columnas, antes de realizar la inserción, corre esta sentencia SQL:

SET IDENTITY_INSERT MiTabla ON

Corre tu proceso de sincronización o inserción de datos, y no olvides al finalizar regresar la propiedad a su valor inicial, corriendo esta sentencia:

SET IDENTITY_INSERT MiTabla OFF