con - r sql database
RODBC sqlGuardar problemas de creación de tabla (5)
Tengo problemas para crear una tabla utilizando sqlSave de RODBC (o, más exactamente, escribir datos en la tabla creada).
Esto es diferente a las preguntas / respuestas sqlSave existentes, como
- los problemas que estaban experimentando eran diferentes, puedo crear tablas mientras que no podían y
- Ya incorporé sin éxito sus soluciones, como cerrar y volver a abrir la conexión antes de ejecutar sqlSave, también
- El mensaje de error es diferente, con la única excepción de una publicación que fue diferente en las 2 formas anteriores
Estoy usando MS SQL Server 2008 y R de 64 bits en un RDP de Windows.
Tengo un marco de datos simple con solo 1 columna llena de enteros de 3, 4 o 5 dígitos.
> head(df)
colname
1 564
2 4336
3 24810
4 26206
5 26433
6 26553
Cuando intento usar sqlSave, no se escriben datos en la tabla. Además, un mensaje de error lo hace parecer que la tabla no se puede crear aunque la tabla realmente se crea con 0 filas.
Basado en una sugerencia que encontré, intenté cerrar y volver a abrir la conexión RODBC justo antes de ejecutar sqlSave. Aunque uso append = TRUE
, intenté abandonar la tabla antes de hacer esto, pero no afecta nada.
> sqlSave(db3, df, table = "[Jason].[dbo].[df]", append = TRUE, rownames = FALSE)
Error in sqlSave(db3, df, table = "[Jason].[dbo].[df]", :
42S01 2714 [Microsoft][ODBC SQL Server Driver][SQL Server]There is already
an object named ''df'' in the database.
[RODBC] ERROR: Could not SQLExecDirect ''CREATE TABLE [Jason].[dbo].[df]
("df" int)''
También intenté usar sqlUpdate () en la tabla una vez que se creó. No importa si lo creo en R o SQL Server Management Studio, obtengo la table not found on channel
errores que table not found on channel
Finalmente, tenga en cuenta que también he intentado esto sin append = TRUE y al crear una nueva tabla, así como con y sin la opción rownames.
El Sr. Flick del #R de Freenode me hizo verificar si podía leer en la tabla vacía usando sqlQuery y de hecho, puedo.
Actualizar
Me he acercado un poco con los siguientes pasos:
- Creé una conexión ODBC que va directamente a mi base de datos dentro del servidor SQL, en lugar de solo a la base de datos predeterminada (maestra), luego especificando la ruta a la tabla dentro de la
table =
o nombre de latablename =
declaraciones - Creó la tabla en SQL Server Management Studio de la siguiente manera
GO
CREATE TABLE [dbo].[testing123](
[Person_DIMKey] [int] NULL
) ON [PRIMARY]
GO
En RI usé
sqlUpdate
con mi nueva conexión ODBC y sin corchetes alrededor del nombre de la tablaAhora sqlUpdate () ve la tabla, sin embargo, se queja de que necesita una columna única
Indicando que la única columna en la tabla es la columna única con
index = colname
daindex = colname
resultado un error que dice que la columna no existeDejé caer y recreé la tabla especificando una clave principal,
GO
CREATE TABLE [dbo].[jive_BNR_Person_DIMKey](
[jive_BNR_Person_DIMKey] [int] NOT NULL PRIMARY KEY
) ON [PRIMARY]
GO
que generó una clave principal e índice (según la interfaz GUI de SQL Sever Management Studio) llamado PK__jive_BNR__2754EC2E30F848ED
- Especifiqué este índice / clave como la única columna en sqlUpdate () pero me aparece el siguiente error:
Error in sqlUpdate(db4, jive_BNR_Person_DIMKey, tablename = "jive_BNR_Person_DIMKey", :
index column(s) PK__jive_BNR__2754EC2E30F848ED not in database table
Para el registro, estaba especificando el nombre correcto de la columna (no "colname") para el índice; gracias a MrFlick por solicitar una aclaración.
Además, estos pasos están numerados del 1 al 7 en mi publicación, pero StackOverflow restablece la numeración de la lista varias veces cuando se muestra. Si alguien puede ayudarme a limpiar ese aspecto de este post, lo agradecería.
Además de algunas de las respuestas publicadas anteriormente, aquí está mi solución. NOTA: Utilizo esto como parte de un pequeño proceso de ETL, y la tabla de destino en el DB se descarta y vuelve a crear cada vez.
Básicamente, usted quiere nombrar su marco de datos de lo que su tabla de destino se llama:
RodbcTest <- read.xlsx(''test.xlsx'', sheet = 4, startRow = 1, colNames = TRUE, skipEmptyRows = TRUE)
Luego, asegúrese de que su cadena de conexión incluya la base de datos de destino (no solo el servidor):
conn <- odbcDriverConnect(paste("DRIVER={SQL Server};Server=localhost//sqlexpress;Database=Charter;Trusted_Connection=TRUE"))
después de eso, ejecuto un sqlQuery simple que condicionalmente descarta la tabla si existe:
sqlQuery(conn, "IF OBJECT_ID(''Charter.dbo.RodbcTest'') IS NOT NULL DROP TABLE Charter.dbo.RodbcTest;")
Entonces, finalmente, ejecute sqlSave sin el parámetro de tabla nombre param, que creará la tabla y la poblará con su marco de datos:
sqlSave(conn, RodbcTest, safer = FALSE, fast = TRUE)
Después de horas de trabajar en esto, finalmente pude hacer que sqlSave funcione mientras especificaba el nombre de la tabla: respiración profunda, por dónde empezar. Aquí está la lista de cosas que hice para que esto funcione:
- Abra el Administrador ODBC de 32 bits y cree un DSN de usuario y configúrelo para su base de datos específica. En mi caso, estoy creando una tabla temporal global, así que me vinculé a tempdb. Use este nombre de conexión en su
odbcConnection(Name)
. Aquí está mi códigomyconn2 <- odbcConnect("SYSTEMDB")
. - Luego
columnTypes <- list(Record = "VARCHAR(10)", Case_Number = "VARCHAR(15)", Claim_Type = "VARCHAR(15)", Block_Date = "datetime", Claim_Processed_Date = "datetime", Status ="VARCHAR(100)")
mis tipos de datos con el siguiente código:columnTypes <- list(Record = "VARCHAR(10)", Case_Number = "VARCHAR(15)", Claim_Type = "VARCHAR(15)", Block_Date = "datetime", Claim_Processed_Date = "datetime", Status ="VARCHAR(100)")
. - Luego actualicé mis tipos de clases de marcos de datos usando
as.character
yas.Date
para que coincidan con los tipos de datos enumerados anteriormente. - Ya creé la tabla porque he estado trabajando en ella durante horas, así que tuve que dejar la tabla usando
sqlDrop(myconn2, "##R_Claims_Data")
. - Luego ejecuté:
sqlSave(myconn2, MainClmDF2, tablename = "##R_Claims_Data", verbose=TRUE, rownames= FALSE, varTypes=columnTypes)
¡Entonces se me cayó la cabeza porque funcionó! Realmente espero que esto ayude a alguien a avanzar. Aquí están los enlaces que me ayudaron a llegar a este punto:
Después de volver a leer el vingette RODBC y aquí está la solución simple que funcionó:
sqlDrop(db, "df", errors = FALSE)
sqlSave(db, df)
Hecho.
Después de experimentar con esto mucho más durante varios días, parece que los problemas se derivaron del uso de las opciones adicionales, particularmente table =
o, equivalentemente, tablename =
. Esas deberían ser opciones válidas, pero de alguna manera logran causar problemas con mi versión particular de RStudio ((Windows, 64 bit, versión de escritorio, compilación actual), R (Windows, 64 bit, v3) y / o MS SQL Server 2008.
sqlSave(db, df)
también funcionará sin sqlDrop(db, "df")
si la tabla nunca existió, pero como mejor práctica estoy escribiendo try(sqlDrop(db, "df", errors = FALSE), silent = TRUE)
antes de todas sqlSave
sentencias sqlSave
en mi código.
Hemos tenido este mismo problema, que después de un poco de prueba lo resolvimos simplemente al no usar corchetes en el esquema y la referencia del nombre de la tabla.
es decir, en lugar de escribir
table = "[Jason].[dbo].[df]"
en cambio escribir
table = "Jason.dbo.df"
Aprecio que esto ya pasó mucho tiempo atrás de la pregunta original, pero solo para cualquier otra persona que posteriormente se tropiece con este problema, así es como lo resolvimos. Como referencia, descubrimos esto escribiendo un simple cuadro de datos de 1 elemento en una nueva tabla, que cuando se inspeccionó en SQL contenía los corchetes en el nombre de la tabla.
Me he encontrado con el mismo problema. La forma en que lo encontré a su alrededor es crear una tabla vacía usando la sintaxis SQL de CREATE TABLE
y luego adjuntarla a través de sqlSave
. Por alguna razón, cuando lo probé a su manera, pude ver el nombre de la tabla en la base de datos MSSQL, incluso después de que arrojó el mensaje de error que mostró arriba, pero estaría vacío.