webForumDet fria alternativet

Göre INSERT i en loop

19 svar · 908 visningar · startad av devotion

devotionMedlem sedan jan. 20013 582 inlägg
#1

Hej!

Jag har följande kod, där jag vill göra en insert till en annan tabell. Men hur gör jag det för att undvika att ha ett databasanrop i loopen? :)

'SQL-fråga
	sSQL = "SELECT * FROM [tblTask] WHERE [PlanStartDate] >= '" & tmStartDate & "' AND [PlanStartDate] < '" & tmStopDate & "'"
	Rs.Open sSQL, Conn
	
	while not rs.EOF
	            'INSERT till tblContractTemplate
		rs.MoveNext
	wend

Mvh
Henrik

TravoniMedlem sedan okt. 20041 556 inlägg
#2

Måste du köra en loop då?

Funkar inte detta:

sSQL = "INSERT INTO ANNAN_TABELL (id, annat1, annat2) SELECT id, annat1, annat2 FROM [tblTask] WHERE [PlanStartDate] >= '" & tmStartDate & "' AND [PlanStartDate] < '" & tmStopDate & "'"
conn.execute(sSQL),,128
devotionMedlem sedan jan. 20013 582 inlägg
#3

Hej!
Ja, jag måste göra en loop... :)

mvh
Henrik

@ndersMedlem sedan juni 200032 969 inlägg
#4

Beror på vilken dbms man använder.

devotionMedlem sedan jan. 20013 582 inlägg
#5

@nders skrev:

Beror på vilken dbms man använder.

:(

MS SQL....

:)

Mvh
Henrik

@ndersMedlem sedan juni 200032 969 inlägg
#6

Då kan man konkatenera ihop flera frågor och köra i en fet batch.

strsql = "insert into blah..." & vbcrlf & _
         "insert into blah..." & vbcrlf & _
         "insert into blah..."
oconn.execute strsql,,128
Peter SMedlem sedan dec. 20025 483 inlägg
#7
'SQL-fråga
	sSQL = "SELECT * FROM [tblTask] WHERE [PlanStartDate] >= '" & tmStartDate & "' AND [PlanStartDate] < '" & tmStopDate & "'"
	Rs.Open sSQL, Conn
	limit = 1000
	counter = 0
	set rs2 = server.createobject("adodb.recordset")
	rs2.cursorlocation = adOpenKeyset
	rs2.locktype = adLockBatchOptimistic
	rs2.open "select * from tblContractTemplate where 1 = 0", conn
	while not rs.EOF
	            'INSERT till tblContractTemplate
		rs2.addnew
		rs2.fields("field1") = rs("field1")
		rs2.fields("field2") = rs("field2")
		rs2.fields("fieldn") = rs("fieldn")
		counter = counter + 1
		if counter mod limit = 0 then
			rs2.updatebatch
		end if
		rs.MoveNext
	wend
	if counter mod limit <> 0 then
		rs2.updatebatch
	end if
	rs2.close
@ndersMedlem sedan juni 200032 969 inlägg
#8

Då jag har hört illasinnade rykten om att mitt inlägg inte förstås kommer här en förenkling.

	while not rs.EOF
	        strsql = strsql & "INSERT till tblContractTemplate ......" & vbcrlf
		rs.MoveNext
	wend
	....
	Conn.execute strsql,,128

mvh

CatZMedlem sedan jan. 20022 440 inlägg
#9

Mmm det är lite svårt att förstå marsvins @nders ibland :p

devotionMedlem sedan jan. 20013 582 inlägg
#10

CatZ skrev:

Mmm det är lite svårt att förstå marsvins @nders ibland :p

:moose

emissionMedlem sedan dec. 19996 721 inlägg
#11

devotion skrev:

Hej!
Ja, jag måste göra en loop... :)

Därför att?

devotionMedlem sedan jan. 20013 582 inlägg
#12

emission skrev:

Därför att?

Hmmm... Ja, det kanske jag inte är så säker på... :)

Jag tror det iaf, eftersom jag behöver behandla vissa poster mha vbscript innan jag gör en INSERT.

Mvh
Henrik

devotionMedlem sedan jan. 20013 582 inlägg
#13

@nders skrev:

Då jag har hört illasinnade rykten om att mitt inlägg inte förstås kommer här en förenkling.

	while not rs.EOF
	        strsql = strsql & "INSERT till tblContractTemplate ......" & vbcrlf
		rs.MoveNext
	wend
	....
	Conn.execute strsql,,128

mvh

Finns det någo riska att att göra en batch med en massa insert och update?

Behöver man använda transaktioner i några lägen?

Mvh
Henrik

@ndersMedlem sedan juni 200032 969 inlägg
#14

Transaktioner ska du använda om du vill att alla eller ingen av dina frågor i ett block ska gå igenom.

Risken med att köra SQL i batcher på detta vis är att du egentligen inte har någon kontroll på vad som går galet om något gör det. Om dina batcher är stora (eller rättare sagt: tar lång tid att köra) kan exekveringen avbrytas av connection-timeouten.

devotionMedlem sedan jan. 20013 582 inlägg
#15

Hej igen!

Jag har fäljande kod:

'**********************
'
'
'**********************

Option Explicit

'**********************

Sub main()

	dim Conn, Rs, sSQL
	dim sOldName, sOldSign, sNewName, sNewSign
	
	
	'Öppna databasen
	Set Conn=CreateObject("ADODB.Connection")
	Conn.Open Application.sDbConnectionString
	
	Set Rs=CreateObject("ADODB.Recordset")
	
	'SQL-fråga
	sSQL = "SELECT [Name], [Sign], [Custom1] AS NewName, [Custom2] AS NewSign FROM [tblUsers]"
	Rs.Open sSQL, Conn
	
	while not rs.EOF
	
		sOldName = Rs("Name")
		sOldSign = Rs("Sign")
		sNewName = Rs("NewName")
		sNewSign = Rs("NewSign")
		
		If sNewName <> "" then
			'tblTask
			sSQL= sSQL & "UPDATE [tblTask] SET [Modified] = GETDATE(), [User] = '" & sNewName & "' WHERE [User] = '" & sOldName & "'" & vbcrlf
			sSQL= sSQL & "UPDATE [tblTask] SET [Modified] = GETDATE(), [CreatedBy] = '" & sNewName & "' WHERE [CreatedBy] = '" & sOldName & "'" & vbcrlf
			sSQL= sSQL & "UPDATE [tblTask] SET [Modified] = GETDATE(), [Owner] = '" & sNewName & "' WHERE [Owner] = '" & sOldName & "'" & vbcrlf
			
			'tblTime
			sSQL= sSQL & "Update [tblTime] Set [Modified] = GETDATE(), [User] = '" & sNewName & "' WHERE [User] = '" & sOldName & "'" & vbcrlf
		end if
		rs.MoveNext
	wend
	
	Conn.Execute sSQL,,128
	
	Rs.Close
	Set Rs=Nothing
	Set Conn=Nothing
		
End sub

Det är ca 150 poster i tblUsers, ca 400 000 poster i tblTask, ca 100 000 poster i tblTime.

Det blir ju en himla massa frågor.. :)

När jag kör koden så får jag följande felmeddelande:

Protocol error in tds stream

Vad kan man göra åt detta?

Mvh
Henrik

devotionMedlem sedan jan. 20013 582 inlägg
#16

Hittade felet...

Av någon anledning följde värdet på sSQL med in i loopen. Löstes med att sätta sSQL till "" innan loopen. Sen ändrade jag på timeouten mha conn.Command=120

Mvh
Henrik

emissionMedlem sedan dec. 19996 721 inlägg
#17

Det räcker med fyra frågor. Du behöver ingen loop.

UPDATE t SET t.Modified = GETDATE(), t.User = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.User=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.CreatedBy = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.CreatedBy=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.Owner = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.Owner=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.User = n.Custom1
FROM tblTime t
INNER JOIN tblUsers n ON t.User=n.Name AND n.Custom1<>''

(De tre översta går att slå ihop till en fråga, men det tjänar man inget på)

devotionMedlem sedan jan. 20013 582 inlägg
#18

emission skrev:

Det räcker med fyra frågor. Du behöver ingen loop.

UPDATE t SET t.Modified = GETDATE(), t.User = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.User=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.CreatedBy = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.CreatedBy=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.Owner = n.Custom1
FROM tblTask t
INNER JOIN tblUsers n ON t.Owner=n.Name AND n.Custom1<>''

UPDATE t SET t.Modified = GETDATE(), t.User = n.Custom1
FROM tblTime t
INNER JOIN tblUsers n ON t.User=n.Name AND n.Custom1<>''

(De tre översta går att slå ihop till en fråga, men det tjänar man inget på)

Aha! :)

Det var ju fiffigt! (y)

Mvh
Henrik

@ndersMedlem sedan juni 200032 969 inlägg
#19

Jag tyckte vi kom fram till att vi behövde en loop?

devotionMedlem sedan jan. 20013 582 inlägg
#20

@nders skrev:

Jag tyckte vi kom fram till att vi behövde en loop?

Hmmm... verkar som jag yrat runt lite och skrivit en annan fråga i en gammal tråd...

Kanske skulle splitta den...

Mvh
Henrik

137 ms totalt · 3 externa anrop · v20260731065814-full.cf67ef55
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
134 ms — hämta tråd, inlägg och bilagor (db)